本文共 2215 字,大约阅读时间需要 7 分钟。
本篇文章主要描述虚拟继承中内存分布情况,当然,可能会不太完全正确,希望大家多多指正
我们看下面一种情景:
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: void func() { }};
为了更加方便理解,用图表示:
如上图,那么就会出现问题:类D中的成员变量 int a,如果访问a,就会出现二义性问题,到底是B中的a,还是C中的A,并且会造成数据冗余问题。其中,对于二义性问题,我们加访问限定即可。例如 C::a;但对于数据冗余问题却没有办法解决。
于是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: void func() { }};
如果,类中带有虚函数。内存结构会变为怎样??
class A{ public: A(int v = 100) :X(v) { }; virtual void foo(void) { } int X;};class B :virtual public A{ public: B(int v = 10) :Y(v), A(100) { }; virtual void fooB(void) { } int Y;};class C : virtual public A{ public: C(int v = 20) :Z(v), A(100) { } virtual void fooC(void) { } int Z;};class D : public B, public C{ D(int v = 40) :B(10), C(20), A(100), L(v) { } virtual void fooD(void) { } int L;};对于类A,内存布局: 对于类B,内存布局: 对于类D,内存布局:
class A{ public: virtual void funA();}; class B : public A{ public: virtual void funB();}
class A{ public: virtual void funA();}; class B : virtual public A{ public: virtual void funB();}
上述两种继承有什么区别??一种普通继承,一种虚拟继承
首先,我们知道,如果一个类中有虚函数,那么就会有一个虚表,有一个指针指向这个虚表。
对于A,内存布局如下: 对于普通继承,继承的虚函数和本有的虚函数共用同一个虚表 则普通继承 B布局如下:但对于虚拟继承来说,不管是基类还是派生类都需要有一个指针来维护自己的虚表,并且还要有一个指针指向虚基表,其中存放偏移量
有了上面的基础,来看几道题:
//第一种情况class a { virtual void func();}; class b:public virtual a{ virtual void foo(); }; //第二种情况class a { virtual void func(); }; class b :public a { virtual void foo(); }; //第三种情况class a { virtual void func(); char x; }; class b:public virtual a { virtual void foo();}; //第四种情况 class a { virtual void func() char x; }; class b:public a { virtual void foo(); };
对于每种情况,分别计算 sizeof(a), sizeof(b)的大小
结果: 第一种:4,12 第二种:4,4 第三种:8,16 第四种:8,8参照上述普通继承和虚拟继承的区别,就知道原因了。
转载地址:http://acwdb.baihongyu.com/