一、面向对象程序设计的基本特点
1.1 抽象
-
指对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程
-
数据抽象
- 描述某类对象的属性或状态,即此类对象与其他类对象的区别
-
行为抽象
-
描述某类对象的共同行为或功能特征
以人为例,对其进行抽象。
共同属性:姓名、性别、年龄等等,则数据抽象:string name, string sex, int age
共同的行为:吃饭、走路、学习等等,则行为抽象:
eat(), walk(), study()
-
1.2 C++面向对象三大特性
- 封装:将数据和操作数据的函数代码进行有机结合,形成 “ 类 ”,其中的数据和函数都是类的成员
- 继承:允许在保存原有类特性的基础上,进行更具体、更详细的说明
- 多态:一段程序能处理多种类型对象的能力
二、类和对象的基本概念
2.1 封装
-
目的:
-
增强安全性和简化编程,使用者不需要具体了解实现细节,只需要通过外部接口,以特定的权限进行访问,使用类的成员
-
意义:
- 将属性和行为作为一个整体
- 将属性和行为加以权限控制
-
语法:
class ClassName { 访问权限: 属性 行为 }
2.2 类和对象
- 类(class)
- 对逻辑上相关的函数和数据的封装,是对问题的抽象描述
- 在面向对象程序设计中,程序模块是由类构成的
- 对象(object)
- 是具有类类型的变量
- C++认为万事万物皆为对象,对象具有属性 和行为
- 具有相同性质的对象,可以抽象为类
- 例如,人属于人类,人作为对象,属性包括姓名、性别、年龄等,行为包括吃饭、走路、学习等
- 类中的属性和行为,统称为成员
- 属性:成员属性,成员变量
- 行为:成员函数,成员方法
2.3 类的定义
2.3.1 语法
// 类名称通常将首字母写成大写
class 类名{
public:
公有成员(外部接口) // 任何外部函数都可访问
private:
私有成员 // 只允许本类中的函数访问
protected:
保护型成员 // 与继承有关
}
// 实例化一个对象
类名 对象名;
// 访问数据成员
对象名.数据成员名
// 调用函数成员
对象名.函数成员名(参数表)
示例:
// 封装一个圆类,求圆的面积和周长
class Circle{
public:
// 属性:半径
int radius;
// 行为:获取圆面积;获取圆周长
double findArea();
double findPerimeter();
};
int main(){
Circle c;
c.radius = 10;
std::cout << "圆的面积:" << c.findArea() << std::endl;
std::cout << "圆的周长:" << c.findPerimeter() << std::endl;
}
2.3.2 成员访问权限
- public、protected和private是访问权限修饰符。
- 被public修饰的属性和函数可以在类内部与类外部被访问
- 被protected和private修饰的属性和函数只能在类内部被访问
- 成员函数可以访问本类中任何成员。一般的做法是将需要被外界调用的成员函数指定为public,他们是类的对外接口
- 有的函数并不是准备为外界调用的,而是为本类中的成员函数所调用的,就应该将它们指定为private
- 一般将属性定义为私有,行为定义为公有
- struct和class的区别:默认的访问权限不同
- struct 默认权限为公共
- class 默认权限为私有
示例:
class Clock{
public:
void setTime(int newH, int newM, int newS);
void showTime();
private:
int hour, minute, second;
}
2.3.3 类的成员函数
-
描述类的行为,对封装的数据进行操作的方法
-
函数的原型声明要写在类体中,函数的具体实现写在类定义外
-
类成员函数的默认值,一定要写在类定义中
-
语法:
返回值类型 类名::函数成员名(参数表){ 函数体 }
示例:
#include <iostream> using namespace std; class Clock { public: void setTime(int newH = 0, int newM = 0, int newS = 0); void showTime(); private: int hour, minute, second; }; // 类成员函数setTime void Clock::setTime(int newH, int newM, int newS) { hour = newH; minute = newM; second = newS; } // 类成员函数showTime void Clock::showTime() { cout << hour << ":" << minute << ":" << second; } int main() { Clock myClock; // 定义对象 myClock.setTime(8, 30, 30); // 通过“.”操作符实现对象成员函数的访问 myClock.showTime(); return 0; }
2.4 多文件编写代码
2.4.1 多文件结构
通常一个项目至少划分为3个文件:
- 类定义文件(*.h文件)
- 写类的声明,包括了所有函数的函数头
- 类实现文件(*.cpp文件)
- 写类的定义
- 注意要引用类定义文件,
#include *.h
- 定义成员函数时函数名称前要加上类名:
类名::函数
,例如:Clock::setTime
- 类使用文件(*.cpp,主函数文件)
- 创建类对象并进行调用
- 注意要引用类定义文件,
#include *.h
更为复杂的程序,可以将每一个类都用单独的定义和实现文件
2.4.2 例子:点和圆的关系
-
所有代码在同一个源文件内
# include <iostream> using namespace std; class Point { //点类 public: void setX(int x) { m_X = x; } //设置x int getX() { return m_X; } //获取x void setY(int y) { m_Y = y; } //设置y int getY() { return m_Y; } //获取y private: int m_X; int m_Y; }; class Circle { //圆类 public: void setR(int r) { m_R = r; } //设置半径 int getR(){ return m_R; } //获取半径 void setCenter(Point center){ m_Center = center; } //设置圆心 Point getCenter(){ return m_Center; } //获取圆心 private: int m_R; //半径 // //在类中可以让另一个类作为本类的成员 // Point m_Center; //圆心 }; //判断点和圆的关系 void isInCircle(Circle &c, Point &p){ //计算两点之间距离平方 int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) + (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //计算半径的平方 int rDistance = c.getR() * c.getR(); //判断关系 if(distance == rDistance){ cout << "点在圆上" << endl; }else if(distance > rDistance){ cout << "点在圆外" << endl; }else{ cout << "点在圆内" << endl; } } int main(){ //创建圆 Circle c; c.setR(10); Point center; center.setX(10); center.setY(0); c.setCenter(center); //创建点 Point p; p.setX(10); p.setY(10); //判断关系 isInCircle(c, p); }
-
多文件编写
-
点类头文件point.h(写点类的类声明)
# pragma once # include <iostream> using namespace std; class Point { //点类 public: void setX(int x); //设置x int getX(); //获取x void setY(int y); //设置y int getY(); //获取y private: int m_X; int m_Y; };
-
点类源文件point.cpp(写点类的类定义)
# include "point.h" //设置x void Point::setX(int x) { m_X = x; } //获取x int Point::getX() { return m_X; } //设置y void Point::setY(int y) { m_Y = y; } //获取y int Point::getY() { return m_Y; }
-
圆类头文件circle.h(写圆类的类声明)
# pragma once # include <iostream> using namespace std; class Circle { //圆类 public: void setR(int r) { m_R = r; } //设置半径 int getR(){ return m_R; } //获取半径 void setCenter(Point center){ m_Center = center; } //设置圆心 Point getCenter(){ return m_Center; } //获取圆心 private: int m_R; //半径 Point m_Center; //圆心 };
-
圆类源文件circle.cpp(写圆类的类定义)
# include "circle.h" //设置半径 void Circle::setR(int r){ m_R = r; } //获取半径 int Circle::getR(){ return m_R; } //设置圆心 void Circle::setCenter(Point center){ m_Center = center; } //获取圆心 Point Circle::getCenter(){ return m_Center; }
-
主函数main.cpp(调用类)
# include <iostream> # include "circle.h" # include "point.h" using namespace std; //判断点和圆的关系 void isInCircle(Circle &c, Point &p){ //计算两点之间距离平方 int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) + (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY()); //计算半径的平方 int rDistance = c.getR() * c.getR(); //判断关系 if(distance == rDistance){ cout << "点在圆上" << endl; }else if(distance > rDistance){ cout << "点在圆外" << endl; }else{ cout << "点在圆内" << endl; } } int main(){ //创建圆 Circle c; c.setR(10); Point center; center.setX(10); center.setY(0); c.setCenter(center); //创建点 Point p; p.setX(10); p.setY(10); //判断关系 isInCircle(c, p); }
-