0. 基本语法

继承是面向对象的三大特性之一。

class 子类 : 继承方式 父类

从父类继承来的表现其共性,而新增的成员表现其个性。

1. 继承方式

三种继承方式

  • public
  • protected
  • private
  • 父类中的private成员,无论哪种方式都不能访问。

2. 继承中的对象模型

问题:从父类继承来的成员,哪些属于子类对象中?

输出子类的sizeof可以看出,父类中的所有非静态成员都会被子类继承下去,无论哪种继承方式。

3. 父类和子类的构造和析构顺序

构造:先base后son
析构:恰恰相反,先son后base

4. 同名成员的处理

  • 要访问子类成员:直接访问
  • 要访问父类成员:加上作用域 son.base::a

  • 父子类出现重名成员函数时,子类会屏蔽掉父类中所有的同名函数(如果父类中有重载,也全都屏蔽掉),如果想访问,就需要加上父类作用域。因为这是在重写父类中的非虚函数,该函数是在编译阶段完成地址绑定的。如果非要重写非虚函数,在设计上是矛盾的,父类把该函数设计成非虚函数的本意就是不希望子类去更改该函数。

5. 多继承

C++允许一个类继承多个类
语法:class 子类 : 继承方式 父类1, 继承方式 父类2。。。
多继承可能会引发父类中有同名成员出现,需要加作用域区分。
C++实际开发中不建议使用多继承。

6. 菱形(钻石)继承

b类和c类继承于a类,d类又同时继承于b类和c类,就叫做菱形继承。

会出现的问题:

  • 两个父类会有相同的数据,需要加以作用域进行区分。
  • 菱形继承会导致数据有两份(来自b和来自c的都有一份),导致资源浪费。此时使用虚基类可以解决。

vbptr虚基类指针会指向vbtable虚基类表。

虚继承可能实际中不太会用到,因为多继承都很少用到,大概率是在面试中出现,知道底层实现的原理即可。