C++多态多重继承与虚继承结合时对内存布局(sizeof)的影响

参考文献:《深度探索C++对象模型》

                     https://bbs.csdn.net/topics/390083150

                     https://blog.csdn.net/u011841639/article/details/39156347

运行平台:Visual Studio 2015(32bits

我在上一篇博客(https://blog.csdn.net/m0_38014304/article/details/84286266(看了这一篇就不用看上一篇了)中探讨了C++中虚继承对类的sizeof大小的影响,而当虚继承与多重继承、多态联系在一起时,其sizeof的结果使得我又产生了困惑。这次我关于类中编译器附加的“虚函数表指针”和“虚基类指针”进行了相关研究,主要针对存在多态的虚继承的对象模型,在此特别感谢大佬(https://blog.csdn.net/u011841639/article/details/39156347)所给的启发,我们开始吧。

源码:

# include <iostream>

using namespace std;

class X
{ 
public:
  virtual ~X() {}
protected:
  int m_x;
};

class Y :virtual public X
{
public:
// virtual void test_y() {}
protected:
//int m_y;
};

class Z :virtual public X
{
public:
  virtual void test_z() {}
//int m_z;
};

class A:public Y, public Z
{
public:
  virtual void test_a() {}
};

class B
{
public:
  virtual ~B() {}
};

class C
{
public:
  virtual ~C() {}
};

class D : public B, public C
{
public:
  virtual void test_d() {}
};

class E : public D 
{
public:
  virtual void test() {}
};

int main(void)
{
   	cout << "X size: " << sizeof(X) << endl;
	cout << "Y size: " << sizeof(Y) << endl;
	cout << "Z size: " << sizeof(Z) << endl;
	cout << "A size: " << sizeof(A) << endl;

	cout << "==========================" << endl;
	cout << "B size: " << sizeof(B) << endl;
	cout << "C size: " << sizeof(C) << endl;
	cout << "D size: " << sizeof(D) << endl;
	cout << "E size: " << sizeof(E) << endl;

	return 0;
}

运行结果如下:

 

1.  存在多态的虚继承

class X、class Y、class Z和class A类之间的关系如下:

通过设置“项目->属性->C/C++->命令行中添加/d1reportSingleClassLayoutX”可在编译时查看class X的内存布局,class Y、class Z和class A依次类推,不过一次我只能设置一个(如果哪位大佬可以一次设置多个请留言告诉小弟),4个类的内存布局如下:

1>  class X	size(8):
1>  	+---
1>   0	| {vfptr}
1>   4	| m_x
1>  	+---
1>  class Y	size(12):
1>  	+---
1>   0	| {vbptr}
1>  	+---
1>  	+--- (virtual base X)
1>   4	| {vfptr}
1>   8	| m_x
1>  	+---
1>  class Z	size(16):
1>  	+---
1>   0	| {vfptr}
1>   4	| {vbptr}
1>  	+---
1>  	+--- (virtual base X)
1>   8	| {vfptr}
1>  12	| m_x
1>  	+---
1>  class A	size(20):
1>  	+---
1>   0	| +--- (base class Z)
1>   0	| | {vfptr}
1>   4	| | {vbptr}
1>  	| +---
1>   8	| +--- (base class Y)
1>   8	| | {vbptr}
1>  	| +---
1>  	+---
1>  	+--- (virtual base X)
1>  12	| {vfptr}
1>  16	| m_x
1>  	+---

可见,存在多态的虚继承时(大前提!!不存在多态的虚继承请看上一篇博客):

(1)派生类与基类不共享虚函数表指针,如果派生类添加了新的虚函数,派生类会在基类的基础上增加一个自己的虚函数表指针,例如class Z与class X,这就是为什么class Z会比class Y多一个指针大小的原因。

(2)在多层虚继承中,每一个派生类都会有自己的虚基类指针,虚基类指针只有一个并且是永远不会共享的,例如class A与class X,class A并没有从class Y和class Z中继承虚基类指针,只是继承了虚函数表指针,但是class A并没有生成自己的虚函数表指针,这是因为class A不是虚继承自class Y和class Z,因此派生类class A和基类class Y与class Z共享虚函数表指针(详见第二部分),且派生类class A里有自己单独的虚基类指针。

2. 存在多态的非虚多重继承

class B、class C、class D和class E类之间的关系如下:

4个类的内存布局如下:

1>  class B	size(4):
1>  	+---
1>   0	| {vfptr}
1>  	+---
1>  class C	size(4):
1>  	+---
1>   0	| {vfptr}
1>  	+---
1>  class D	size(8):
1>  	+---
1>   0	| +--- (base class B)
1>   0	| | {vfptr}
1>  	| +---
1>   4	| +--- (base class C)
1>   4	| | {vfptr}
1>  	| +---
1>  	+---
1>  class E	size(8):
1>  	+---
1>   0	| +--- (base class D)
1>   0	| | +--- (base class B)
1>   0	| | | {vfptr}
1>  	| | +---
1>   4	| | +--- (base class C)
1>   4	| | | {vfptr}
1>  	| | +---
1>  	| +---
1>  	+---

可见,在非虚继承的多重继承体系中,派生类与基类共享虚函数表指针,由于非虚继承,派生类内部没有虚基类指针。

总结

主要对存在多态的虚继承的内存布局进行了详细讨论,是对上一篇博客的深入研究,希望能帮助到对C++对象模型内存布局感兴趣的各位,小弟才疏学浅,如有错误还请大佬多多指教。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值