第13章 类继承
13.1 一个简单的基类
class RatedPlayer : public TableTennisPlayer
{
...
}
冒号指出RatedPlayer继承TableTennisPlayer类,public声明TableTennisPlayer是一个共有继承,称为公有派生。
使用公有派生,基类的公有成员将成为派生类的公有函数,私有部分也将成为派生类的一部分,但只有通过基类公有函数和保护方法才能访问。
派生类可以有自己的构造函数,可以根据需要添加额外的成员数据和方法。
初始化基类成员:可以通过:TableTennisPlayer(fn , ln , ht)成员初始化列表初始化基类成员。
构造派生类的顺序:1.创建基类对象,2.通过成员初始化列表调用基类构造函数,3.初始化派生类的数据成员。
基类指针可以不进行显示类型转化地指向派生类,基类引用可以在不进行显示类型转化地引用派生类。反之不允许。
基类指针只能调用基类方法。
13.3 多态公有继承
同一个方法在派生类和基类中的行为是不同的。这种较复杂的行为称为多态。
实现多态公有继承方法:1.在派生类中重新定义基类方法。2.使用虚方法。
基类使用virual关键字的方法称为虚方法。
如果没有使用关键字virtual,程序将根据引用类型或指针类型选择方法;如果使用了virtual,程序将根据引用或指针指向的对象的类型来选择方法。
重写了基类的函数,调用基类该函数需要使用作用域解析运算符。
析构函数一定是虚函数。即使基类不需要显示析构函数提供服务,也要提供析构函数,即使它不执行任何操作。
构造函数一定不能是虚函数。
友元函数不能是虚函数。
如果要在派生类中重新定义基类的方法,则将它设置为虚方法;否则,设置为非虚方法。
重新定义基类方法不是重载,而是隐藏基类方法。
如果重新定义继承的方法,应确保与原来的原型完全相同,但如果在返回类型是基类引用或指针,则可以修改为指向派生类的引用或指针。
如果重新定义的方法被重载了,则应在派生类中重新定义所有的基类方法。
13.5 访问控制:protected
访问控制protected派生类的成员可以直接访问基类的保护成员,但不能访问基类的私有成员。
13.6 抽象基类
C++通过使用纯虚函数提供未实现的函数。
在虚函数原型后加=0声明为纯虚函数,在类中可以不定义该函数。
类声明中包含纯虚函数时,则不能创建该类的对象。
13.7 继承和动态内存分配
当基类和派生类都采用动态内存分配时,对于构造函数,这是通过在初始化成员列表币调用基类的复制构造函数来完成的。
派生类的显式赋值运算符必须负责所有继承的基类对象的赋值,可以通过显式调佣基类赋值运算符来完成这项工作。
13.8 类设计回顾
对于基类,即使它不需要析构函数,也应提供一个虚析构函数。
成员函数属性:
函数 | 能否继承 | 成员函数友元 | 默认能否生成 | 能否为虚函数 | 是否可以有返回类型 |
---|---|---|---|---|---|
构造函数 | 否 | 成员 | 能 | 否 | 否 |
析构函数 | 否 | 成员 | 能 | 能 | 否 |
= | 否 | 成员 | 能 | 能 | 能 |
& | 能 | 任意 | 能 | 能 | 能 |
转换函数 | 能 | 成员 | 否 | 能 | 否 |
() | 能 | 成员 | 否 | 能 | 能 |
[] | 能 | 成员 | 否 | 能 | 能 |
-> | 能 | 成员 | 否 | 能 | 能 |
op= | 能 | 任意 | 否 | 能 | 能 |
new | 能 | 静态成员 | 否 | 否 | void* |
delete | 能 | 静态成员 | 否 | 否 | void |
其他运算符 | 能 | 任意 | 否 | 能 | 能 |
其他成员 | 能 | 成员 | 否 | 能 | 能 |
友元 | 否 | 友元 | 否 | 否 | 能 |