c++继承中的经典题型
- 什么是菱形继承?菱形继承的问题是什么?
- 什么是菱形虚拟继承?如何解决数据冗余和二义性的?
- 继承和组合的区别?什么时候用继承?什么时候用组合?
问题一
什么是菱形继承?
菱形继承是指有一个基类被两个不同的类所继承,且存在一个类继承于这两个类而形成的一种菱形关系。
如下图所示
菱形继承的问题是什么?
菱形继承有数据冗余和二义性的问题
如下图
问题二
什么是菱形虚拟继承?
菱形虚拟继承通过在多个类同时继承一个类时加上virtual关键字,使得继承父类的变量在全局只有一份。这样,多个类可以同时找到并修改这个唯一的父类变量。
如下图
如何解决数据冗余和二义性的?
菱形虚拟继承依靠虚基表来解决数据二义性问题。通过虚拟继承的类的栈中都会存一个虚基表指针,标识父类变量的偏移量,以找到父类变量,从而确保全局只有一个父类的变量。
我们以下图列详细解释
上图是菱形继承的内存表,由此可看出B,C中各维护着两份不同的A成员对象,这里体现出数据冗余,而通过D对象调用A的成员变量就无法得出调用哪一个A对象,这里可以体现出其二义性
而该图是菱形虚拟继承内存表,这里可以分析出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C。
通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。
问题三
继承和组合的区别
*public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
*组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
*基类的内部细节对子类可见,继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
*对象组合要求被组合的对象具有良好定义的接口,对象的内部细节是不可见的,因此组合类之间没有很强的依赖关系,耦合度低
什么时候用继承?什么时候用组合?
实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用继承,可以用组合,就用组合。