详谈详谈C++中虚基类在派生类中的内存布局中虚基类在派生类中的内存布局
今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题
而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的原理如下所示:
在C++中,obj是一个类的对象,p是指向obj的指针,该类里面有个数据成员mem,请问obj.mem和p->mem在实现和效率上有
什么不同。
答案是:只有一种情况下才有重大差异,该情况必须满足以下答案是:只有一种情况下才有重大差异,该情况必须满足以下3个条件:个条件:
((1)、)、obj 是一个虚拟继承的派生类的对象是一个虚拟继承的派生类的对象
((2)、)、mem是从虚拟基类派生下来的成员是从虚拟基类派生下来的成员
((3)、)、p是基类类型的指针是基类类型的指针
当这种情况下,p->mem会比obj.mem多了两个中间层。(也就是说在这种情况下,p->mem比obj.mem要明显的慢)
WHY??
如果好奇心比较重的话,请往下看如果好奇心比较重的话,请往下看 :
1、虚基类的使用,和为多态而实现的虚函数不同,是为了解决多重继承的二义性问题。
举例如下:
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;
};
上面这种菱形的继承体系中,如果没有virtual继承,那么D中就有两个A的成员int a;继承下来,使用的时候,就会有很多二义
性。而加了virtual继承,在D中就只有A的成员int a;的一份拷贝,该拷贝不是来自B,也不是来自C,而是一份单独的拷贝,
那么,编译器是怎么实现的呢??
在回答这个问题之前,先想一下,sizeof(A),sizeof(B),sizeof(C),sizeof(D)是多少?(在32位x86的linux2.6下面,或者在
vc2005下面)在linux2.6下面,结果如下:sizeof(A) = 4; sizeof(B) = 12; sizeof(C) = 12; sizeof(D) = 24;sizeof(B)为什么是
12呢,那是因为多了一个指针(这一点和虚函数的实现一样),那个指针是干嘛的呢?
那么sizeof(D)为什么是24呢?那是因为除了继承B中的b,C中的c,A中的a,和D自己的成员d之外,还继承了B,C多出来的2
个指针(B和C分别有一个)。再强调一遍,D中的int a不是来自B也不是来自C,而是另外的一份从A直接靠过来的成员。
如果声明了D的对象d: D d;
那么d的内存布局如下:
vb_ptr: 继承自B的指针
int b: 继承自B公有成员
vc_ptr:继承自C的指针
int c: 继承自C的共有成员
int d: D自己的公有成员
int a: 继承自A的公有成员
那么以下的用法会发生什么事呢?那么以下的用法会发生什么事呢?
D dD;
评论0