虚拟继承时类的大小

Kun*_*mar 5 c++ polymorphism virtual

有人可以解释在涉及虚函数的虚拟继承的情况下类的大小.

   class A{
          char k[ 3 ];
          public:
          virtual void a(){};
          };

   class B : public  A{
          char j[ 3 ];
          public:
          virtual  void b(){};
          };

   class C : public virtual A{
          char i[ 3 ];
          public:
          virtual void c(){};
          };

   class D : public B, public C{
          char h[ 3 ];
          public:
          virtual void d(){};
          };
Run Code Online (Sandbox Code Playgroud)

类的大小输出是:

    sizeof(A): 8
    sizeof(B): 12
    sizeof(C): 16
    sizeof(D): 32
Run Code Online (Sandbox Code Playgroud)

我正在使用的编译器是 gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)

Dav*_*eas 7

sizeof(A):8

数组中的3个字节,1个字节的填充,4个字节的vptr(指向vtable的指针)

sizeof(B):12

子对象:8,3个字节用于额外阵列,1个字节填充

sizeof(C):16

这对你来说可能是令人惊讶的...一个子对象:8,3个字节用于额外数组,1个字节填充,4个字节指向A

每当您具有虚拟继承时,虚拟基础子对象相对于完整类型的开始的位置是未知的,因此将额外的指针添加到原始对象以跟踪虚拟基础的位置.考虑这个例子:

struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
Run Code Online (Sandbox Code Playgroud)

的位置A相对于所述开始B时的完整的类型是对象B可以比的位置不同A的子对象B时,它是最后的对象的一部分D.如果这不是显而易见的,假定相对位置是相同的,并检查是否的相对位置A相对于CC最终对象或C在子对象D也可以被保持.

至于最后一个例子,我不太喜欢分析它...但你可以阅读Itanium C++ ABI来获得C++对象模型的具体实现.所有其他实现没有太大差别.


最后的例子:

sizeof(D):32

D包含B子对象(12)和C子对象(16),以及大小为3的附加阵列和一个额外的填充1.

在这种特殊情况下,可能出现的问题是,为什么有两个A子对象,如果C实际上从中继承A,并且答案是虚拟基础意味着对象愿意与层次结构中同样愿意的任何其他类型共享此基础分享它.但是在这种情况下B不愿意分享它的A子对象,所以C需要它自己.

您应该能够通过向不同级别的构造函数添加日志来跟踪此情况.在它的情况下,A它在编译器中取值并从每个扩展类传递不同的值.