9

以下代码来自《Inside the C++ object model》一书

#include <iostream>  
using namespace std;
class X{};
class Y: public virtual X{};
class Z: public virtual X{};
class A: public Y, public Z{};

int main()
{
     cout<<sizeof(X)<<" "<<sizeof(Y)<<" "<<sizeof(Z)<<" "<<sizeof(A)<<endl;
     return 0;
}

在我的电脑(Windows,VS2010)中,输出为:

1 4 4 8

这是我的问题

1、大小(X)=1

书上说当 X 类型生成两个实例时,比如 xa 和 xb。编译在 A 中插入一个字节,以便 xa 和 xb 可以具有不同的地址。我不太明白其中的原因。

2、大小(Y)=4

通过使用虚拟继承,我们会有一个额外的虚拟指针吗?我想这可能与多态中的虚拟指针不同。谁能给我 Y 的内存布局?

谢谢!

4

4 回答 4

6
  1. 当类为空时编译器新一个字符,因此它可以生成不同的对象
  2. sizeof(Y)=4 因为它是虚拟继承,构造会生成 vptr 表,在 32 位系统上是 4 字节
  3. 如果您使用 Visual Studio,请在 properties->C/C++/Command 中使用 /d1reportAllClassLayout 来生成对象布局类 Y 对象布局将在 Visual Studio 上:
  4. Stanley B. Lippman 所著的《Inside C++ object model》一书很好地解释了这一点

 
        class Y size(4):
            +---
            0     | {vbptr}
            +---
            +--- (virtual base X)
            +---
Y::$vbtable@: 0 | 0 1 | 4 (Yd(Y+0)X)

vbi: class offset o.vbptr o.vbte fVtorDisp X 4 0 4 0
于 2012-10-31T11:50:48.103 回答
1

空类的 sizeof 始终返回 1。这是空类的单个虚拟字节。

A 持有虚拟表中的两个条目,一个用于 Y,另一个用于 Z

所以两个指针的大小,即 8。

Y 和 Z 在它们的虚拟表中都有一个 X 条目,因此大小为 4。

于 2012-10-31T11:41:32.260 回答
1

一个 A 对象将包括一个 Y 对象、一个 Z 对象(按此顺序)和只有一个X 对象(由 Y 和 Z 中的指针引用),因为 Y 和 Z 实际上都从 X 继承,因此意味着当多重继承出现时只玩一个 X 对象将在子类中实例化。A 仍然有两个对象(一个 Y,一个 Z),因此 sizeof = 8(因为它们的 sizeof = 4)。但是 Y 和 Z 中指向 X 对象的指针都指向同一个地址。

继承树将如下所示:

  X
 / \
 Y Z
 \ /
  A
于 2012-10-31T11:52:21.593 回答
0

类 - 必须 - 至少 1 个字节的原因是说我们有一个 X 数组。如果它们是 0 个字节,那么 &array[1] 将具有与 &array[3] 相同的地址,这是没有人预料到的,会破坏代码,如果您必须编写代码来检查这一点,那会很烦人,而且通常没有任何意义。

Y 将只是

static void* virtual_ptr1 //note this is in virtual table and cannot be edited  

您可以将 vtables(指向类和虚函数的虚拟指针)视为无法手动/代码编辑的静态变量(或至少不应该)。将其视为编译器保留的静态变量

于 2012-10-31T12:32:28.110 回答