在下面的代码中,为什么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
{
};
我认为,因为我们有虚拟基类,所以应该只有A的一个实例。
没错。
在下面的代码中,为什么D的大小是16个而不是8个字节?
在我的系统上,D是24个字节。
D包含一个B子对象(不包括A),一个D子对象(不包括A)和一个虚拟A子对象。
由于基数不是标准布局,因此不需要空基数优化,并且每个基数都有唯一的地址,因此尽管没有子对象本身也占用了内存。
此外,虚拟继承必须使用虚拟表来处理共享库的构造,因此实例将具有指向该表的虚拟指针。
在下面的代码中,为什么D的大小是16个而不是8个字节?
在任何情况下,所有这些派生类都不能(实际上(*))具有与其虚拟基数A
相同的大小:
A
基础子对象是B
对象(或另一个派生对象的子对象)的C
和D
子对象的直接基础。(*)我知道可能有违反该断言的实现方法,但它们的效率低下,笨拙且难以保证线程安全,甚至在线程化程序中效率也较低。
由于关系是一对多的,因此无法固定类布局(与非虚拟成员或成员不同)。唯一基础子对象的位置取决于所创建的确切派生类。
X
类的[g]值表示类型为X
的实例或派生自X
的类;因此,当使用不引用已知对象的(g)lvalue时(使用本地声明对象的名称时,根据定义的类型是已知的),基础子对象的地址在运行时根据类型(或地址)确定)嵌入在实例中的信息。
B
和C
需要携带此类信息来定位虚拟基准。