虚拟继承情况下类的大小
Size of the classes in case of virtual inheritance
有人可以解释一下在涉及虚函数的虚拟继承的情况下类的大小吗?
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(){};
};
类大小的输出是:
sizeof(A): 8
sizeof(B): 12
sizeof(C): 16
sizeof(D): 32
我正在使用的编译器是 gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
数组中 3 个字节,1 个字节尺寸(A(: 8
填充,4 个字节用于 VPTR(指向 vtable 的指针(
尺寸(B(: 12
子对象:8,额外数组为 3 个字节,1 个字节填充
尺寸(C(: 16
这对你来说可能是令人惊讶的...子对象:8,3 字节用于额外数组,1 字节填充,4 字节指针指向 A
每当具有虚拟继承时,虚拟基子对象相对于完整类型开头的位置都是未知的,因此会向原始对象添加一个额外的指针来跟踪虚拟基的位置。请考虑以下示例:
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
当完整类型为B
时,A
相对于B
对象的开头的位置可以不同于B
的A
子对象在D
的最终对象中的位置。如果这不明显,假设相对位置相同,并检查A
相对于C
的相对位置是否也可以保持C
最终对象或D
中的C
子对象。
至于最后一个例子,我不太想分析它......但您可以阅读 Itanium C++ ABI,了解C++对象模型的具体实现。所有其他实现没有太大区别。
最后一个例子:
尺寸(D(: 32
D 包含一个 B 子对象 (12( 和一个 C 子对象 (16(,以及一个大小为 3 的附加数组和一个额外的填充位 1。
在这种特殊情况下,可能出现的问题是,如果C
虚拟地继承自A
,为什么有两个A
子对象,答案是虚拟基础意味着对象愿意与层次结构中也愿意共享它的任何其他类型共享此基础。但在这种情况下,B
不愿意共享它A
子对象,所以C
需要它自己的。
您应该能够通过将日志添加到不同级别的构造函数来跟踪这一点。在A
的情况下,让它在编译器中获取一个值,并从每个扩展类传递不同的值。
sizeof(C)
不仅仅是sizeof(B)
,因为类型为C的对象(因为它实际上是从A继承的(将包含一个指针(除了vptr,B类型的对象也将包含(指向它从A继承的自身部分。 "了解虚拟函数、多重继承、虚拟基类和 RTTI 的成本",他的书《更有效C++
要知道数据结构的实际大小,你可以说编译者不要使用 pack(1( 在内存中对齐它 #pragma。要保存当前的打包设置并在以后恢复它们,您还可以使用 #pragma 包(推送(和 #pragma 包(流行(。
这是我对所有字节使用位置的最佳猜测:
Avptr Bvptr CVptr DVptr k j i h k' j' i' TOTAL
============= ========================================= =====
sizeof(A): 8 4 4 8
sizeof(B): 12 4 4 4 12
sizeof(C): 16 4 4 4 4 16
sizeof(D): 32 4 4 4 4 4 4 4 4 32
哪里:
- VPTR 每个占用 4 个字节(64 位指针(
- char 数组每个占用 4 个字节(向上舍入以对齐(
- k'、j' 和 i' 是通过 C 而不是 B 继承的那些变量的副本。
- 在双重继承的情况下如何处理非标准构造函数
- 循环依赖,在继承类的情况下使用覆盖方法
- 是否可以在不修改父类的情况下将成员变量初始化推迟到继承的类?
- 类成员在继承的情况下用作模板参数
- c++ 中的函数重载如何在没有钻石继承的情况下工作?
- 虚拟继承情况下类的意外大小
- 虚拟继承情况下的 vtable
- 有什么理由在没有继承的情况下声明一个虚拟方法
- 在我的情况下,多重继承是一种好的设计模式吗?
- 模板和unique_ptr继承情况下的重载解决方案
- 默认情况下,我如何在不使用继承的情况下使用所有构造函数
- 在这种情况下,继承类如何工作??.
- 在多个继承的情况下,C 编译器如何处理成员变量内存偏移
- 在 c++ 中类继承的情况下强制延迟方法解析
- 如何在不继承手柄的情况下分叉处理
- C++:在不是所有派生类都预先已知的情况下使用继承
- 如何在不使用继承的情况下'rename'模板实例化?
- 为什么在多重继承的情况下,QObject需要成为第一个
- 虚拟继承情况下类的大小
- 多继承情况下的构造函数