【发布时间】:2019-10-11 18:07:51
【问题描述】:
我有一个简单的对象,用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,没问题。但是为什么 Derive1/Derive2 的 sizeof 是 32? c++ 对象模型为它添加了一个额外的指针,对吧?但是这个额外的指针实际上做了什么,为什么有必要添加这个额外的 8 字节指针?我认为这里没有任何必要性。
非常感谢。
【问题讨论】:
-
我认为它添加了两个指向虚拟继承的
Base1或Base2子对象的指针。 -
这取决于 abi:例如 Itanium C++ abi。根据这个 abi,类型的大小与您观察到的相同。 D1 布局为
D1{ C1{vtable_ptr:8bytes};C2{vtable_ptr:8bytes};Base1:16bytes}} -
想一想——您可以将派生对象的指针强制转换为任何基类,并且在第一个字节处应该有一个有效的 vtable 指针。因此,在多重继承的情况下,每个基类都有一个 vtable 是很合乎逻辑的
标签: c++ object inheritance model virtual