11. 虚继承

在继承的过程中有时会出现用一个类派生出多个子类,又通过多继承将多个子类派生出一个子类。这种创建的子类对象中可能会包含多个基类对象。

以下是多继承中的一个著名案例,菱形继承(也叫钻石继承)。

  A
 / \
B   C
 \ /
  D

B 类继承自 A类,因此 B 类对象即包含自身的成员,也会包含 A 类的成员。同理 C 类对象也会包含 A 类的成员。又因为 D 类继承自 B 类和 C 类,因此 D 类的对象就有两份 A 类的成员变量(一份来自于 B 类,一份来自于 C 类)。而 D 类根本就不需要两份 A 类成员(会出现冲突)。解决这个问题的语法是使用虚继承

虚继承的语法

class 子类名: virtual 继承方式 父类名 {
};

示例

// filename: diamond.cpp
#include <iostream>

using namespace std;

class A {
    public:
        A() : a(1) {}
        void method() {
            cout << "a:" << a << endl;
        }
    private:
        int a;
};
class B : virtual public A {
    public:
        B() : A(), b(2) {}
    private:
        int b;
};
class C : virtual public A {
    public:
        C() : A(), c(3) {}
    private:
        int c;
};
class D : public B, public C {
    public:
        D() : B(), C(), d(4) {}
    private:
        int d;
};

int main(int argc, char * argv[]) {
    D d;
    d.method();
    return 0;
}

编译和运行结果如下:

weimz@mzstudio:~$ g++ -o diamond diamond.cpp
weimz@mzstudio:~$ ./diamond 
a:1

上述代码中, B 类和 C 类都是虚继承自 A 类,因此在多继承创建 D 类时D 类中只有一个 A 类的对象,否则编译则会出现成员函数或者成员变量出现争议(ambiguous) 的编译错误。