gpt4 book ai didi

c++ - 关于 C++ 中的多重继承、虚拟基类和对象大小的问题

转载 作者:IT老高 更新时间:2023-10-28 23:09:47 24 4
gpt4 key购买 nike

以下代码打印 20,即 sizeof(z) 为 20。

#include <iostream.h>
class Base
{
public:
int a;
};

class X:virtual public Base
{
public:
int x;
};

class Y:virtual public Base
{
public:
int y;
};

class Z:public X,public Y
{
};

int main()
{
Z z;
cout << sizeof(z) <<endl;
}

而如果我在这里不使用虚拟基类,即对于以下代码:sizeof(z) 是 16。

#include <iostream.h>
class Base
{
public:
int a;
};

class X:public Base
{
public:
int x;
};

class Y:public Base
{
public:
int y;
};

class Z:public X,public Y
{
};

int main()
{
Z z;
cout << sizeof(z) <<endl;
}

为什么在第一种情况下 sizeof(z) more(20) ?不应该是 12,因为 Base 将被包括在内在 Z 中只有一次?

最佳答案

我们来看看这两个案例的类布局。

没有虚拟,你有两个基类(“X”和“Y”),每个基类都有一个整数,每个类都集成了一个“基”基类,它也有一个整数。那是 4 个整数,每个 32 位,总共 16 个字节。

Offset  Size  Type  Scope  Name
0 4 int Base a
4 4 int X x
8 4 int Base a
12 4 int Y y
16 size (Z members would come at the end)

(编辑:我在 DJGPP 中编写了一个程序来获取布局并调整表格以解决它。)

现在让我们谈谈虚拟基类:它们用指向共享实例的指针替换类的实际实例。您的“Z”类只有一个“Base”类,“X”和“Y”的两个实例都指向它。因此,您在 X、Y 和 Z 中有整数,但只有一个 Z。这意味着您有三个整数,即 12 个字节。但是 X 和 Y 也有一个指向共享 Z 的指针(否则他们不知道在哪里找到它)。在 32 位机器上,两个指针将额外增加 8 个字节。这总计您看到的 20 个。内存布局可能看起来像这样(我还没有验证过...... ARM 有一个示例,其中顺序是 X、Y、Z,然后是 Base):

Offset  Size        Type  Scope  Name  Value (sort of)
0 4 Base offset X ? 16 (or ptr to vtable)
4 4 int X x
8 4 Base offset Y ? 16 (or ptr to vtable)
12 4 int Y y
16 4 int Base a
20 size (Z members would come before the Base)

所以内存差异是两件事的结合:少一个整数和多两个指针。与另一个答案相反,我不相信 vtables 支付任何(编辑)直接(/编辑)滚动,因为没有虚拟功能。

编辑:ppinsider 提供了有关 gcc 案例的更多信息,他在其中演示了 gcc 通过使用否则为空的 vtable(即,没有虚函数)来实现指向虚拟基类的指针。这样,如果有虚函数,它就不需要类实例中的额外指针,需要更多内存。我怀疑缺点是额外的间接访问基类。

我们可能期望所有编译器都这样做,但也许不是。 ARM第 225 页讨论了虚拟基类,但未提及 vtable。第 235 页专门针对“具有虚拟函数的虚拟基类”,并有一个图表指示内存布局,其中 X 和 Y 部分的指针与指向 vtable 的指针是分开的。我建议任何人不要想当然地认为指向 Base 的指针将以表的形式实现。

关于c++ - 关于 C++ 中的多重继承、虚拟基类和对象大小的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/396327/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com