问题本质
当派生类通过多条路径继承同一个基类时,会导致:
- 数据冗余:派生类中包含多份基类的成员(浪费内存)。
- 二义性:访问基类成员时,编译器无法确定使用哪一条继承路径的成员。
代码实现:
class Animal { public: int age; }; class Bird : public Animal {}; class Mammal : public Animal {}; class Platypus : public Bird, public Mammal {}; // 菱形继承问题复现
Platypus p; // p.age = 5; // 错误:ambiguous access of 'age'(二义性) cout << sizeof(p); // 输出8(包含两份Animal::age)解决方案:虚继承(Virtual Inheritance)
1.修改继承方式
class Bird : virtual public Animal {}; // 虚继承 class Mammal : virtual public Animal {}; class Platypus : public Bird, public Mammal {};2.内存布局变化
- 普通继承:
Platypus包含两份Animal子对象。 - 虚继承:
Platypus通过虚基类指针共享唯一Animal子对象
验证:
Platypus p; p.age = 5; // 合法,无二义性 cout << sizeof(p); // 输出24(64位)(含虚基表指针)虚继承的底层原理
编译器会为虚继承的类生成:
- 虚基类指针(vbptr):指向虚基类子对象。
- 虚基类表(vbtable):存储偏移量信息。
内存结构示例:
内存布局(64位系统)
| 组成部分 | 大小 | 说明 |
|---|---|---|
| Bird部分 | 8字节 | 虚基类指针(指向共享的Animal) |
| Mammal部分 | 8字节 | 虚基类指针(指向同一个Animal) |
| Animal部分 | 4字节 | int age |
| 内存对齐填充 | 4字节 | 按8字节对齐补齐 |
| 总大小 | 24字节 |
### **构造顺序的特殊规则** 虚基类的构造函数**优先于所有非虚基类**调用: ```C++ Platypus p; // 调用顺序:Animal() → Bird() → Mammal() → Platypus()