我有一个简单的对象,可以使用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作为添加虚拟函数(指向vtable的vptr)将增加一个额外的指针大小,因此它们的大小为24,没问题。但是为什么Derive1 / Derive2的size为32? C ++对象模型向它添加了一个额外的指针,对吗?但是,这个额外的指针实际上是做什么的?为什么有必要添加这个额外的8byte指针?我觉得这里没有必要。
非常感谢。
答案 0 :(得分:1)
合理的布局:
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;