the*_*z03 2 c++ multiple-inheritance virtual-inheritance memory-layout
#include <iostream>
using namespace std;
class A {
int a;
};
class B1 : virtual public A {
int b1;
};
class B2 : virtual public A {
int b2;
};
class C : public B1, public B2 {
int c;
};
int main() {
A obj1; B1 obj2; B2 obj3; C obj4;
cout << sizeof(obj1) << endl;
cout << sizeof(obj2) << endl;
cout << sizeof(obj3) << endl;
cout << sizeof(obj4) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
4
16
16
40
Run Code Online (Sandbox Code Playgroud)
在上面的 c++ 程序中,A 的大小是 4,因为它只有一个 int,B1 的大小是 16,因为 (int+ int + 虚拟指针) 与 B2 相同
但是为什么C的大小是40???
结果可能因您使用的编译器和系统架构而异。例如,msvc 19.28 x64给出这个不言自明的结果(使用选项/d1reportAllClassLayout得到它):
class C size(44):
+---
0 | +--- (base class B1)
0 | | {vbptr}
8 | | b1
| | <alignment member> (size=4)
| | <alignment member> (size=4)
| +---
16 | +--- (base class B2)
16 | | {vbptr}
24 | | b2
| | <alignment member> (size=4)
| | <alignment member> (size=4)
| +---
32 | c
| <alignment member> (size=4)
+---
+--- (virtual base A)
40 | a
+---
Run Code Online (Sandbox Code Playgroud)
但msvc 19.28 x86结果将是:
class C size(24):
+---
0 | +--- (base class B1)
0 | | {vbptr}
4 | | b1
| +---
8 | +--- (base class B2)
8 | | {vbptr}
12 | | b2
| +---
16 | c
+---
+--- (virtual base A)
20 | a
+---
Run Code Online (Sandbox Code Playgroud)
需要注意的是,上面的类布局清楚地展示了虚继承的特点,即基类实例(A)的一个副本被孙子派生类(C)继承。如果A::a数据成员是公共的,我们可以在类的成员函数中使用以下语句C:
void C::foo() {
B2::a = 1;
B1::a = 2;
std::cout << B2::a << " " << B1::a << " " << A::a; // Output: 2 2 2
}
Run Code Online (Sandbox Code Playgroud)
但是如果你不使用虚拟继承(而只是public),那么类的C布局将是这样的:
class C size(20):
+---
0 | +--- (base class B1)
0 | | +--- (base class A)
0 | | | a
| | +---
4 | | b1
| +---
8 | +--- (base class B2)
8 | | +--- (base class A)
8 | | | a
| | +---
12 | | b2
| +---
16 | c
+---
Run Code Online (Sandbox Code Playgroud)
我们会有两个基类成员变量的副本 A
void C::foo() {
B2::a = 1;
B1::a = 2;
std::cout << B2::a << " " << B1::a; // Output: 1 2. `A::a` ambiguity error
}
Run Code Online (Sandbox Code Playgroud)