多重继承
C++允许一个派生类继承自另一个类。
同时又允许一个派生类同时继承多个基类。这被称为多重继承。
声明多重继承的方法
class D: public A, public B, public C
{
//...
};
D是多重继承的派生类。它以公有继承的方式同时继承自A、B、C。
构造函数构造顺序
D:D()
:A(), B(), C()
{
}
调用顺序为:先调用基类的构造函数,在执行派生类的构造函数。基类的构造函数调用顺序按照声明派生类时基类的出现顺序。
析构函数调用顺序与构造顺序相反
同名成员函数的二义性
在单继承下,基类的public 和protected 成员可以直接被访问,就像它们是派生类的成员一样,对多继承这也是正确的。但是在多继承下,派生类可以从两个或者更多个基类中继承同名的成员。然而在这种情况下,直接访问是二义的,将导致编译时刻错误。
例如,如果A和B 都定义了一个成员函数print(),
则如下语句:
D d;
d.print();
将导致编译时错误,即使这两个通过继承得到的成员函数定义了不同的参数类型:
原因在于继承得到的成员函数没有构成派生类中的重载函数,因此,对于print()调用,编译器在解析的时候,只是使用了针对print 的名字解析。解决的方法是在方法前加上所属的类d.A::print();
虚基类
尽管在派生列表中不允许同一个基类出现两次,但实际上派生类可以多次继承同一个类。
派生类通常会含有继承链上每个类对应的子部分。在上面的两种情况中,class D都间接地继承了class A两次,那么意味着class D中包含了class A的两份拷贝。所以在一个class D的对象中将含有2组class A的成员,此时若不加前缀限定符直接使用某个成员将引发“二义性”错误:
为了解决上述问题,C++提供了虚继承的机制。虚继承的目的是令某个类作出声明,承诺愿意共享它的基类。共享的基类子对象称为虚基类。在这种机制下,不论虚基类在继承体系中出现多少次,在派生类中都只包含唯一一个共享的虚基类子对象。我们指定虚基类的方式是在派生列表中添加关键字virtual:
class B: virtual public A
{
}
class C: virtual public A
{
}
class D: public B,public C
{
}
含有虚基类的对象的构造顺序与一般的多重继承的构造顺序稍有区别:先初始化虚基类子对象(最低层派生类负责),然后按派生列表中的顺序依次对直接基类(非虚)进行初始化。