目录
1.单继承和多继承
2.菱形继承
3.虚继承解决菱形继承
3.1使用方法
3.2虚继承原理
4.继承和组合
1.单继承和多继承
一个子类只有一个父类称为单继承
一个子类有多个父类称为多继承
2.菱形继承
菱形继承是多继承的一种复杂的情况
这里会出现一个问题,Assistant这个类中继承了两个Person类,造成了数据的冗余和二义性。
例:
可以通过指定类域解决但是数据的冗余没有解决
3.虚继承解决菱形继承
3.1使用方法
虚继承可以在person被teacher和student继承时使用
在前面加个virtual
3.2虚继承原理
用一个简单的菱形继承模型,在借助内存窗口观察。
class A
{
public:
int _a;
};
class B : public A
//class B : virtual public A
{
public:
int _b;
};
class C : public A
//class C : virtual public A
{
public:
int _c;
};
class D : public B, public C
{
public:
int _d;
};
int main()
{
D d;
d.B::_a = 1;
d.C::_a = 2;
d._b = 3;
d._c = 4;
d._d = 5;
return 0;
}
不加virtual时候看内存窗口很明显D对象中有两个a对象,有数据冗余。
加virtual之后对象A被放在了最底端,之前存放A的位置变成了一个地址。
这个地址指向基虚表,叫做基虚表指针,基虚表中存的时偏移量,通过偏移量可以找到A。
0x01 0F FD A4 + 0x00 00 00 14 = 0x 01 0F FD B8 正好是A的位置。
4.继承和组合
继承是is-a的关系,就是每一个派生类都是一个基类。
组合是has-a的关系,没事派生类都有一个基类。
这就是组和
继承是白箱复用,对基类内部可见,一定程度破坏了封装,耦合度高。
组和是黑箱复用,对基类内部不可见,没有破坏封装,耦合度低。
组合比继承的可维护性更高,能用组合的地方就用组合。