Loading... # C++菱形继承与虚继承的应用 ## 菱形继承 如图所示,派生类`C`继承了基类`B1`和`B2`,而基类`B1`和`B2`都是`A`的派生类。 ## 非虚继承 ```cpp #include <iostream> using std::cout; using std::endl; using std::string; class A { public: string identity = "class A"; string baseIdentity; A(string parent) : baseIdentity(parent) {cout << "create class A" << endl;}; }; class B1 : public A { public: string identity = "class B1"; B1() : A("from B1") {cout << "create class B1" << endl;}; }; class B2: public A { public: string identity = "class B2"; B2() : A("from B2") {cout << "create class B2" << endl;}; }; class C: public B1, public B2 { public: string identity = "class C"; C() : B1(), B2() {cout << "create class C" << endl;}; }; int main() { C instacne; cout << "!: " << instacne.identity << endl; //cout << "!: " << instacne.A::identity << endl; cout << "!: " << instacne.B1::identity << endl; cout << "!: " << instacne.B2::identity << endl; } ``` 输出: ``` create class A create class B1 create class B2 create class C class C class A ``` 从中可以看出,使用非虚继承,基类`A`的构造函数被构造了两次,因此,主函数`int main(){...}`中被注释掉的那行代码是无法编译的,因为事实上实例`instance`中`B::identity`有两个独立的来源:从`B1`继承来的和从`B2`继承来的,所以编译器给出了如下报错: > Ambiguous conversion from derived class 'C' to base class 'A': class C -> class B1 -> class A class C -> class B2 -> class A ## 虚继承 ```cpp #include <iostream> using std::cout; using std::endl; using std::string; class A { public: string identity = "class A"; string baseIdentity; A(string parent) : baseIdentity(parent) {cout << "create class A" << endl;}; }; class B1 : virtual public A { public: string identity = "class B1"; B1() : A("from B1") {cout << "create class B1" << endl;}; }; class B2: virtual public A { public: string identity = "class B2"; B2() : A("from B2") {cout << "create class B2" << endl;}; }; class C: public B1, public B2 { public: string identity = "class C"; C() : B1(), B2(), A("from C") {cout << "create class C" << endl;}; }; int main() { C instacne; cout << "!: " << instacne.identity << endl; cout << "!: " << instacne.A::identity << endl; cout << "!: " << instacne.B1::identity << endl; cout << "!: " << instacne.B2::identity << endl; cout << "!: " << instacne.A::baseIdentity << endl; } ``` 输出: ``` create class A create class B1 create class B2 create class C !: class C !: class A !: class B1 !: class B2 !: from C ``` 从中可以看出,使用虚继承 - 基类`A`仅被构造一次 ; - 忽略 `B1`,`B2`中关于`A`的参数初始式; - 在派生类`C`中必须调用`A`的构造函数对基类`A`进行初始化 ; - 在上例中被注释掉的语句现在可以通过编译,因为建立派生类`C`时仅建立了`A`的一个副本,没用歧义。 最后修改:2020 年 07 月 06 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏