目录
1.多继承,菱形继承
单继承:一个子类只有一个直接父类时称这个继承关系为单继承
多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承
菱形继承:菱形继承是多继承的一种特殊情况。
- 菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant 的对象中Person成员会有两份。
2.虚继承
2.1标准的菱形继承
我们看下面的代码,一个标准的菱形继承,看在内存里面是什么样的,监视窗口被优化过,需要我们使用内存窗口;
class A
{
public:
int _a;
};
class B : public A
{
public:
int _b;
};
class C : 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;
}
2.2虚继承
格式:派生类的访问方式前加一个virtual(注:跟多态的虚函数的virtual没有关系同一个关键词)
原理:虚继承,会让添加关键字的类(B和C)的产生一个虚基表指针,虚基表指针指向保存当前指针到公共虚基量的偏移量;
代码:
class A
{
public:
int _a;
};
class B : virtual public A
{
public:
int _b;
};
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;
}
由上所诉:下面的b和c都是依靠虚基表指针指向的偏移量,找到不在自己类的成员变量的;
int main()
{
D d;
d.B::_a = 1;
d.C::_a = 2;
d._b = 3;
d._c = 4;
d._d = 5;
B &b = d;
C &c = c;
cout << c->_a << " " << b->_a << endl;
return 0;
}
3.总结
虽然虚继承,弥补了菱形继承的坑,但是也付出了很大的代价
- 对象模型更复杂了,学习成本更高
- 有一定效率影响