虚拟继承中大多数派生类的大小

问题描述 投票:0回答:1

在下面的代码中,为什么D的大小是16而不是8字节?

我想因为我们有虚拟基类,所以应该只有A的一个实例。

class A
{
public:
    int x_;
    int y_;
};

class B :  virtual public A
{
};

class C :  virtual public A
{

};

class D :  public B, public C
{
};
c++ multiple-inheritance sizeof virtual-inheritance memory-layout
1个回答
0
投票

我认为,因为我们有虚拟基类,所以应该只有A的一个实例。

没错。

在下面的代码中,为什么D的大小是16个而不是8个字节?

在我的系统上,D是24个字节。

D包含一个B子对象(不包括A),一个D子对象(不包括A)和一个虚拟A子对象。

由于基数不是标准布局,因此不需要空基数优化,并且每个基数都有唯一的地址,因此尽管没有子对象本身也占用了内存。

此外,虚拟继承必须使用虚拟表来处理共享库的构造,因此实例将具有指向该表的虚拟指针。


0
投票

在下面的代码中,为什么D的大小是16个而不是8个字节?

在任何情况下,所有这些派生类都不能(实际上(*))具有与其虚拟基数A相同的大小:

  • 派生类对象与non虚拟直接基础子对象的关系,就像与成员子对象的关系一样,是一对一关系;
  • 派生类对象与虚拟基础子对象的关系是多对一关系:根据定义,特定的虚拟基类子对象可以是多个派生类的direct基础。 A基础子对象是B对象(或另一个派生对象的子对象)的CD子对象的直接基础。
  • (*)我知道可能有违反该断言的实现方法,但它们的效率低下,笨拙且难以保证线程安全,甚至在线程化程序中效率也较低。

由于关系是一对多的,因此无法固定类布局(与非虚拟成员或成员不同)。唯一基础子对象的位置取决于所创建的确切派生类。

X类的[g]值表示类型为X的实例或派生自X的类;因此,当使用不引用已知对象的(g)lvalue时(使用本地声明对象的名称时,根据定义的类型是已知的),基础子对象的地址在运行时根据类型(或地址)确定)嵌入在实例中的信息。

BC需要携带此类信息来定位虚拟基准。

这会使它们大于基准。最派生的类需要空间来容纳所有非虚拟数据库中的位置信息,再加上虚拟数据库本身(如果有任何数据成员,通常放置在末尾)。
© www.soinside.com 2019 - 2024. All rights reserved.