virtual base class的问题

    虚拟继承的实现机制在不同的编译器下方法是不同的,因此造成不同编译器下类对象的大小有差异。先上代码:

  8 #include<iostream>
  9 using namespace std;
 10 class A{
 11     public:
 12         virtual void display1(){}
 13     private:
 14        // int x;
 15 };
 16 class B: public virtual A{
 17     public:
 18         virtual void display2(){}
 19 };
 20 
 21 int main() 
 22 {
 23     A a;
 24     B b;
 25     cout << sizeof(a) << endl;
 26     cout << sizeof(b) << endl;
 27     return 0;
 28 }
~      
在Gcc上测试,此时sizeof(a)和sizeof(b)输出都是4。 但是在VS2013上测试,sizeof(a) = 4, sizeof(b) = 12.a的大小为4没问题,即一个虚表指针的大小,在两个编译器上大小相同。但是sizeof(b)的大小在两种编译器上却差距很大。奇怪!再试下在A中定义一个int型数据:

#include<iostream>
using namespace std;

class A{
public:
	virtual void display1(){}
private:
	int x;
};

class B : public virtual A{
public:
	virtual void display2(){}
};

class C : public virtual A{
public:
	virtual void display3(){}
};

class D : public B, public C{
public:
	virtual void display4(){}
};
int main()
{
	A a;
	B b;
	C c;
	D d;
	cout << sizeof(a) << endl;
	cout << sizeof(b) << endl;
	cout << sizeof(c) << endl;
	cout << sizeof(d) << endl;
	system("pause");
	return 0;
}


在Gcc上测试,此时的输出是:sizeof(a)  = 8, sizeof(b) = 12.但是在VS中测试是:sizeof(a) = 8, sizeof(b) = 16,sizeof(c) = 16, sizeof(d = 24)。A中int型数据+虚表指针大小为8,这个也没有问题。但是b的大小还是不同。编译之后,生成如下窗口信息:

>  class A	size(8):
1>  	+---
1>   0	| {vfptr}
1>   4	| x
1>  	+---
1>  
1>  A::$vftable@:
1>  	| &A_meta
1>  	|  0
1>   0	| &A::display1 
1>  
1>  A::display1 this adjustor: 0
1>  
1>  
1>  class B	size(16):
1>  	+---
1>   0	| {vfptr}
1>   4	| {vbptr}
1>  	+---
1>  	+--- (virtual base A)
1>   8	| {vfptr}
1>  12	| x
1>  	+---
1>  
1>  B::$vftable@B@:
1>  	| &B_meta
1>  	|  0
1>   0	| &B::display2 
1>  
1>  B::$vbtable@:
1>   0	| -4
1>   1	| 4 (Bd(B+4)A)
1>  
1>  B::$vftable@A@:
1>  	| -8
1>   0	| &A::display1 
1>  
1>  B::display2 this adjustor: 0
1>  
1>  vbi:	   class  offset o.vbptr  o.vbte fVtorDisp
1>                 A       8       4       4 0
1>  
1>  
1>  class C	size(16):
1>  	+---
1>   0	| {vfptr}
1>   4	| {vbptr}
1>  	+---
1>  	+--- (virtual base A)
1>   8	| {vfptr}
1>  12	| x
1>  	+---
1>  
1>  C::$vftable@C@:
1>  	| &C_meta
1>  	|  0
1>   0	| &C::display3 
1>  
1>  C::$vbtable@:
1>   0	| -4
1>   1	| 4 (Cd(C+4)A)
1>  
1>  C::$vftable@A@:
1>  	| -8
1>   0	| &A::display1 
1>  
1>  C::display3 this adjustor: 0
1>  
1>  vbi:	   class  offset o.vbptr  o.vbte fVtorDisp
1>                 A       8       4       4 0
1>  
1>  
1>  class D	size(24):
1>  	+---
1>  	| +--- (base class B)
1>   0	| | {vfptr}
1>   4	| | {vbptr}
1>  	| +---
1>  	| +--- (base class C)
1>   8	| | {vfptr}
1>  12	| | {vbptr}
1>  	| +---
1>  	+---
1>  	+--- (virtual base A)
1>  16	| {vfptr}
1>  20	| x
1>  	+---
1>  

    让我们来一个个分析:(1)A的起始地址先存放的是vfptr,即虚函数表指针,占4个字节,然后接下来4个字节存放的是数据x,这样a的大小为8;(2)B虚拟继承自A,首先存放的是自己的vfptr,占4字节。然后是指向虚基类的指针vbptr,也是4字节。最后存放类A,占8字节。这样b的大小为16字节;(3)C与B同理,所以c的大小也是16;(4)D共有继承B和C。首先存放B的虚函数表指针和虚基类指针,占8字节。然后是C的虚函数表指针和虚基类指针,占8字节。最后存放A的数据,占8字节。这样一共24字节。

    在VS的实现机制中,虚基类在子类的子类中只有一个实体,子类共享这个实体。子类怎样定位到基类呢?答案就是虚基类指针,指向虚基类的起始地址(我感觉也有可能是偏移值?)。这样在子类的子类及其派生类中永远保证只有一个虚基类的实体。Gcc的实现机制有时间再研究下。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值