C++ 类与对象
虚函数相关
注意事项
- 基类方法声明中使用virtual可使该方法在基类和派生类中都是虚拟的
- 使用指向对象的引用或者指针来调用虚方法,程序将使用为对象类型定义的方法,而不是引用或者指针类型定义的方法
- 派生类要重新定义基类的方法,一般我们声明为虚拟的
析构函数
析构函数一般是虚函数,除非类不用做基类,因为虚拟析构函数可以按次序来调用对应的析构函数
友元函数和构造函数
这两个函数我们都不需要使用virtual声明
访问控制(protected)
前面我们通过public和private来控制对类成员的访问,这里还有另一种类别使用关键字protected表示
protected和private相似,在类外只有共有类成员才能访问protected部分的类成员,但是如果基类中声明了protected成员,派生类可以直接访问基类中protected成员
抽象基类(abstract base class)
我们一般称抽象基类为ABC
这里举个例子我们为什么需要抽象基类
我们都知道圆是椭圆的一个特殊情况,所以所有的圆都是椭圆,因此我们可以从椭圆中派生圆,但是我们将会发现这里存在问题
椭圆类肯定包括椭圆中心坐标,长半轴,短半轴,方向角,然后和一系列方法,而圆不需要长短半轴来描述其形状大小,圆只需要半径,这样我们直接定义圆类似乎更加方便
但是在方法中两者又有相似的地方,所以我们聪明的C++开发人员就想到是不是可以从两个对象中抽象出他们的共性放在ABC中,然后从ABC派生出椭圆类和圆类
我们使用纯虚函数(pure virtual function)提供未实现的函数
这里简单介绍下纯虚函数
我们简单定义一个ABC类
class BaseEllipse //ABC类
{
private:
double x;
double y;
public:
BaseEllipse(double x0=0, double y0=0):x(x0),y(y0){}
//这里使用了成员初始化列表方法
virtual ~BaseEllipse(){} // 虚构析构函数
void Move(int ny, int ny){x=nx;y=ny;}
virtual double area()const = 0;// 纯虚函数
};
当类声明中包含纯虚函数时,该类是无法创建实例化对象的,纯虚函数就是虚函数后面加上 = 0
当我们创建了派生类后,我们可以分别定义他们从抽象基类继承的纯虚函数(多态)
之后我们就可以创建椭圆和圆的派生类,分别添加它们自己独特的成员和方法
关于对象与类的复习
编译器默认生成的成员函数
默认构造函数
- 默认函数要么没有参数,要么所有的参数都有默认值
- 如果派生类构造函数的成员初始化列表中没有显式地调用基类构造函数,那么将自动调用默认构造函数来构造派生对象地基类部分
- 如果定义了构造函数,则编译器不再提供默认构造函数
复制构造函数
在以下情况下将使用复制构造函数:
- 将新对象初始化为一个同类对象
- 按值将对象传递给函数
- 函数按值返回对象
- 编译器生成临时对象
新对象的每个成员都会被初始化为原始对象相应成员的值
当使用new初始化的成员指针通常需要我们执行深复制,或者类包含需要修改的静态变量时,我们需要自己定义复制构造函数
赋值操作符(=)
- 当需要显式定义复制构造函数时,一般我们也要显式定义赋值操作符
重要的类方法
构造函数
- 它创建新的对象,而其他类方法只是在对象被创建后调用,所以构造函数不会被继承
- 构造函数可以有多种形式
析构函数
- 当我们使用new分配内存时,一定要显式定义析构函数来释放所有的内存
- 对于基类,我们一般使用虚拟析构函数
按值传递对象和传递引用
- 一般我们编写对象作为参数的函数时,我们使用传递引用,提高效率
- 按值传递对象涉及到生成临时拷贝,需要调用复制构造函数,然后调用析构函数,花费的时间较多
返回对象和返回引用
- 一般我们返回引用,理由也是效率高
- 但是当我们需要返回函数中临时创建的对象时,我们不能返回引用,因为函数结束时,这个临时对象就会被析构,所以我们要返回对象,生成一个可以使用的拷贝
什么不能被继承
构造函数,析构函数,赋值操作符都不能被继承
关于C++类与对象的基本知识到这里就完结啦!!!
捞一捞整个系列的博文:
从小白开始学C++类与对象六(类继承)
从小白开始学C++类与对象五(返回类对象的方式,对象指针,嵌套结构,重载<<操作符)
从小白开始学C++ 类与对象四(动态内存分配)
从小白开始学C++ 类与对象三 (操作符重载、友元函数,类的自动转换和强制类型转换)
从小白开始学C++ 类与对象二 (this指针和对象数组)
从小白开始学C++ 类与对象一(创建、定义类、构造函数、析构函数)
都到这里,点个赞呗