c++ - 为什么虚拟继承 2 个类会增加对象大小?

标签 c++ object inheritance model virtual

我有一个简单的对象,用 g++ 在 64 位 ubuntu1804 下编译和运行:

struct Base1{ int mi,mj,mk,mh;};
struct Base2{ int ni,nj,nk,nh;};

struct Child1:virtual Base1{virtual void f(){}};
struct Child2:virtual Base1{virtual void f(){}};
struct Derive1:Child1,Child2{};

struct Child3:virtual Base2{virtual void f(){}};
struct Child4:virtual Base2{virtual void f(){}};
struct Derive2:Child3,Child4{};

struct Final:Derive1,Derive2{};
int main(){
        cout<<"C1="<<sizeof(Child1)<<endl;
        cout<<"C2="<<sizeof(Child2)<<endl;
        cout<<"C3="<<sizeof(Child3)<<endl;
        cout<<"C4="<<sizeof(Child4)<<endl;
        cout<<"D1="<<sizeof(Derive1)<<endl;
        cout<<"D2="<<sizeof(Derive2)<<endl;
        cout<<"F ="<<sizeof(Final)<<endl;
        return 0;
}

程序输出:

$ g++ om.cpp -O2 && ./a.out
C1=24
C2=24
C3=24
C4=24
D1=32
D2=32
F =64

我知道 sizeof(B1) 是 16,而 Child1-Child4 添加虚函数(vptr 指向 vtable)会增加额外的指针大小,所以它们的大小是 24,没问题。但是为什么 sizeof Derive1/Derive2 是 32? C++ 对象模型为它添加了一个额外的指针,对吧?但是这个额外的指针实际上做了什么,为什么有必要添加这个额外的 8byte 指针呢?我认为这里没有任何必要。

非常感谢。

最佳答案

合理的布局:

Final
----------------------
| Derive1
| --------------------
| | Child1
| | ------------------
| | | Pointer to Base1 (8 bytes)
| | ------------------
| | Child2
| | ------------------
| | | Pointer to Base1 (8 bytes)
| | ------------------
| --------------------
| Derive2
| --------------------
| | Child3
| | ------------------
| | | Pointer to Base2 (8 bytes)
| | ------------------
| | Child4
| | ------------------
| | | Pointer to Base2 (8 bytes)
| | ------------------
| --------------------
| Base1
| --------------------
| | mi                 (4 bytes)
| | mj                 (4 bytes)
| | mk                 (4 bytes)
| | mh                 (4 bytes)
| --------------------
| Base2
| --------------------
| | ni                 (4 bytes)
| | nj                 (4 bytes)
| | nk                 (4 bytes)
| | nh                 (4 bytes)
| --------------------
----------------------

总大小:8 + 8 + 8 + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 = 64
请注意,如果您的虚函数不那么琐碎和/或实际上覆盖了某些内容,则此大小可能会增加以容纳 vtable 指针。 (就目前而言,可以完全优化虚拟功能。)

要理解为什么所有这些指针都是必要的,请考虑以下几点:

Final foo;
Child3 * c3 = &foo;
Child4 * c4 = &foo;
Base2 * b23 = c3;
Base2 * b24 = c4;

如果给定c4,您将如何将其转换为指向Base2 的指针?请记住,您不能假设 c4 指向 Final 的一部分;您的解决方案还必须适用于以下各项,并且必须同样适用于 c3

Child4 c4;
Base2 * b24 = &c4;

关于c++ - 为什么虚拟继承 2 个类会增加对象大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56304483/

相关文章:

c++ - 容器比较器使用虚拟实例

javascript - Shopify - 我可以从浏览器控制台访问 JSON 对象,但不能从主题文件访问

java - 即使在Java中初始化子类后,静态变量的值也不会改变

c++ - 这段 C++ 代码是如何工作的?

c++ - QTableWidget单元格更新

c++ - 在 C++ 中将对象创建为私有(private)类变量

javascript - Mozilla Firefox 边距空间

c++ - 编译器错误 : looser throw specifier for destuctor

java - 编译器看不到main方法

c++ - 对相同数量的记录执行 CListCtrl::InsertItem 的不同时间