一、虚继承的核心定位:解决菱形继承的痛点
在讲解虚继承前,先明确其诞生的背景——菱形继承(钻石继承) 是多重继承的典型问题,而虚继承是 C++ 专门设计的解决方案:
- 菱形继承:多个基类继承自同一个'共同基类',最终派生类又同时继承这些基类,导致共同基类的成员在最终派生类中存在多份副本(数据冗余),访问时引发二义性。
- 虚继承:通过
virtual关键字声明继承,让'共同基类'成为虚基类,使其在最终派生类中仅保留一份实例,彻底解决数据冗余和二义性。
二、虚继承的基本语法与核心概念
1. 语法格式
虚继承的关键字 virtual 需加在'继承方式'前,修饰的是'继承行为',而非基类本身:
// 格式:class 派生类 : virtual 继承方式 虚基类 { ... };
class 中间基类 1: virtual public 共同基类 { ... };
class 中间基类 2: virtual public 共同基类 { ... };
class 最终派生类 : public 中间基类 1, public 中间基类 2 { ... };
- 虚基类:被
virtual继承的'共同基类'(比如下面示例中的Animal); - 最终派生类:菱形结构最底层的类(比如下面示例中的
Duck),是唯一负责初始化虚基类的类。
2. 先看问题:普通菱形继承的坑
先通过代码复现菱形继承的核心问题(数据冗余 + 二义性),让你直观感受为什么需要虚继承:
#include <iostream>
using namespace std;
// 共同基类:Animal
class Animal {
public:
int age;
Animal(int a) : age(a) {
cout << "Animal 构造,age=" << a << endl;
}
};
// 中间基类 1:Flyable(普通继承 Animal)
: Animal {
:
( a) : (a) {}
{
cout << << age << endl;
}
};
: Animal {
:
( a) : (a) {}
{
cout << << age << endl;
}
};
: Flyable, Swimmable {
:
( a) : (a), (a) {}
};
{
;
cout << &duck.Flyable::age << endl;
cout << &duck.Swimmable::age << endl;
;
}

