C++继承前言:
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用
目录
-
继承的语法规则
-
父类子类赋值兼容规则
-
重定义和重载的区别
-
父类与子类的默认成员函数
-
继承与友元
-
继承与静态成员
-
菱形继承和虚拟继承
继承的语法规则
父类子类赋值兼容规则
派生类对象可以赋值给基类的对象/基类的指针/基类的引用。这种说法也叫切片或切割
基类对象不能赋值给派生类
基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用
重定义和重载的区别
在继承体系中基类和派生类都有独立的作用域。
子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
注意在实际中在继承体系里面最好不要定义同名的成员。
问:为什么呢?
编译规则:
重载是在链接时完成的,而重定义在编译时就完成了。编译阶段是在链接阶段前面
父类和子类的默认成员函数
构造函数
派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
拷贝构造
派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化
赋值拷贝
派生类的operator=必须要调用基类的operator=完成基类的复制。
析构函数
派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序
继承与友元
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。父亲的朋友不是我(儿子)的朋友
继承与静态成员
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例 。
菱形继承和虚拟继承
菱形继承:
菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。
如何解决呢?
虚拟继承:
虚拟继承可以解决菱形继承的二义性和数据冗余的问题。
这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。