Appearance
继承
- is a 模型(例如,汽车是交通工具)
- PS:has a --> 类包含类(例如,汽车对象有引擎对象的属性)
- PS: use a --> 类包含类,使用它的功能(例如,汽车可多次调用引擎的启动方法)
- 基于已有的类,定义新类
- 能够提供代码的复用性
- 多态的必要条件,没有继承就没有多态
- B 类继承于 A 类
- A 类称为父类
- B 类称为子类或者派生类
格式
cpp
class Child: 继承方式 Parent {}继承方式
public,protected,private- 作用:将父类中的不同访问权限的成员,设置继承到子类中的的不同访问标准

- 继承方式其实就是父类的成员在子类的最高访问权限
- 默认的继承方式是
private
构造函数
- 默认会调用父类的无参构造函数
- 可在初始化列表调用父类的有参构造函数:
cpp
Stu(String n, int p, int m, double s): Person(n,p,m), score(s);
^^^^^^^^^^^^^^- 子类会包含父类的包括私有在内的所有成员,其实是特殊的 has a 关系,在内存中,父类的成员在前

- 可以通过子类对象来声明一个父类指针或引用
Parent *p = &child
函数隐藏
- 当子类的函数名称(不是签名)和父类一致的时候,不会报错,这种现象称作函数隐藏
- 子类对象调用的是子类自己扩展的成员,如果想要使用父类成员,需要在名字前加上父类作用域限定符
特殊成员函数
构造函数
- 构造函数不会被继承
- 需要在子类构造函数中调用父类构造函数,若无则默认调用无参构造
- 父类有有参但无无参构造,则必须显式调用父类构造函数,否则报错
- 先构造父类再构造子类,
析构函数
- 不会继承
- 无需显式调用
- 先析构子类再析构父类
拷贝构造函数
- 不会继承
- 需要显式调用父类拷贝构造函数,默认调用无参构造函数
- 也设计深浅拷贝问题
cpp
Stu &operator =(const Stu &other) {
if(this != &other) {
this->score = other.score;
Person::operator =(other);
}
return *this;
}多重继承
- C++ 支持多重继承,可以成员可继承自多个父类
- 成员重名需要作用域限定符
- 构造顺序与继承顺序有关,与调用构造函数顺序无关
- MultipleInheritance.cpp
虚继承
- 菱形继承问题,也叫钻石继承,一个公共基类派生出多个中间子类,再由其中 N 个中间子类共同派生出一个汇聚子类
- 此时,汇聚子类中,由于不同路线继承关系,会保留多份公共基类继承的成员,造成数据冗余,访问不方便
txt
-----------------------
A ---> 公共基类
/ \
B C ---> 中间子类
\ /
D ---> 汇聚子类
------------------------ 为了解决这个问题,需要使用 virtual 继承
- 在继承方式前加关键字
virtual - 当进行虚继承时,由于汇聚子类保留的一份数据,编译器不知道选取哪一个,直接由公共基类构造(上图的 A)
- DiamondInheritance.cpp