继承
1.单继承
2.多继承
菱形继承----派生类中有多份基类的数据
解决方法:虚继承
虚基类的构造优先级 > 普通基类
画图顺序 非虚继类 > 虚基类 >派生类
(方便画图,以下省去类中的成员方法)
class A
{
public:
int ma;
};
class B : virtual public A
{
public:
int mb;
};
class C : virtual public A
{
public:
int mc;
};
class E
{
public:
int me;
};
class D : public B ,virtual public E, public C
{
public:
int md;
};
(1)第一种情况:
class A
class B : virtual public A
class C : virtual public A
class D : public B , public C
这样一幅图就是菱形继承----导致的问题是派生类中有多份基类的数据
此时A是D的间接基类,B,C是D的基类
此时D的内存布局为:
我们可以看到菱形继承----导致的问题是派生类中有多份基类的数据。此时内存布局中,A::ma 内存重复了,这就导致了空间浪费,其次是你要访问B的ma还是C的ma?访问不明确
于是为了解决多次继承中内存重复的问题,我们引入了虚继承,虚继承就是为了解决多次继承中的内存重复问题
我们把重复基类叫做虚基类,那么A就是虚基类,解决的方法是:
把虚基类放在最下面,原来的位置放虚基类指针,虚基类指针指向虚基类表,里面存放的是对虚基类的偏移
最终D的内存布局为:
我们可以看到菱形继承----导致的问题是派生类中有多份基类的数据。此时内存布局中,A::ma 内存重复了,这就导致了空间浪费,其次是你要访问B的ma还是C的ma?访问不明确
于是为了解决多次继承中内存重复的问题,我们引入了虚继承,虚继承就是为了解决多次继承中的内存重复问题
我们把重复基类叫做虚基类,那么A就是虚基类,解决的方法是:
把虚基类放在最下面,原来的位置放虚基类指针,虚基类指针指向虚基类表,里面存放的是对虚基类的偏移
最终D的内存布局为:
此时构造顺序为:ABCD,析构相反
虚基类的构造优先级>普通基类
画图时先画非虚基类,在画虚基类,最后画派生类
(2)第二种情况:
class A
class B : virtual public A
class C : virtual public A
class D :virtual public B , public C
此时内存布局为“
构造顺序:ABCD
(3)第三种情况:
class A
class B : virtual public A
class C : virtual public A
class E
class D : public B , public C,virtual public E
此时的内存布局为:
(4)第四种情况:
class A
class B : public A
class C : public A
class E
class D : public B ,virtual public E,public C
此时内存布局:
(5)第五种情况:
class A
class B : public A
class C : public A
class E
class D : virtual public E,public B ,public C
此时内存布局为:
此时先声明virtual public E,public B 先看到了基类E,所以先把E放到下面,再处理A
(6)第六种情况:
class A
class B : public A
{
Virtual void func()
}
class C : public A
{
Virtual void func()
}
class D : virtual public B ,virtual public C