定义
关于多重继承,考虑如下的情形:
class A { public: void Foo() {} }; class B : public A {}; class C : public A {}; class D : public B, public C {};
以上类的继承层次关系形成一个“可怕的钻石”,如左图, 但内存布局如右图, D有两份A的“实例”(仅为形象表述)
A A A
/ \ | |
B C ----- Memory Layout ----> B C
\ / \ /
D D
当要调用 D::Foo()时, 就会出现二义性问题:
D d; d.Foo(); // is this B's Foo() or C's Foo() ??
解决方法是使用虚拟继承,相当于告诉编译器,只要一份A的“实例”:
class A { public: void Foo() {} }; class B : public virtual A {}; class C : public virtual A {}; class D : public B, public C {};
然后就可以正常调用 D::Foo():
D d; d.Foo(); // no longer ambiguous如果类的继承关系出现了这种钻石结构,在95%程度上,你的类设计有误(?)。
初始化
虚基类由最低层派生类的构造函数初始化(如果由直接派生类初始化,则基类可能被多次重复初始化)。
ZooAnimal
virtual / \ virtual
Bear Raccoon Endangered
\ | /
Panda
Bear::Bear(std::string name, bool onExhibit): ZooAnimal(name, onExhibit, "Bear") { } Raccoon::Raccoon(std::string name, bool onExhibit) : ZooAnimal(name, onExhibit, "Raccoon") { } // ZooAnimal 由 Panda 的构造函数初始化: Panda::Panda(std::string name, bool onExhibit) : ZooAnimal(name, onExhibit, "Panda"), Bear(name, onExhibit), Raccoon(name, onExhibit), Endangered(Endangered::critical), sleeping_flag(false) { }
如果有以下类:
class Character { /* ... */ }; class BookCharacter : public Character { /* ... */ }; class ToyAnimal { /* ... */ }; class TeddyBear : public BookCharacter, public Bear, public virtual ToyAnimal { /* ... */ };
则构造函数调用顺序如下:
ZooAnimal(); // Bear's virtual base class ToyAnimal(); // immediate virtual base class Character(); // BookCharacter's nonvirtual base class BookCharacter(); // immediate nonvirtual base class Bear(); // immediate nonvirtual base class TeddyBear(); // most derived class基类析构函数的调用顺序总是与构造函数调用顺序相反。
C++ Primer 17.3.5