为支持多继承,一个类的派生表被扩展成支持逗号分割的基类表。例如:
class Panda : public Bear,public Endangered { ... };
每个被列出的基类还必须指定访问级别:public、protected或private之一。如果缺省没有列出,则其缺省值为private。例如:
class Panda : public Bear,Endangered { ... }; //Endangered的访问级别是private
注意:如果一个基类没有明白的指定其访问层次,则将被视为private。所以上面的例子中,Endangered的访问层次是private。
一、在多继承下,基类构造函数被调用的顺序以派生类表中声明的顺序为准。例如:
class Bear : public ZooAnimal { ... };
class Endangered { ... };
class Panda : public Bear,public Endangered { ... };
当我们用Panda定义一个对象时:
Panda ying_yang ;
构造函数的调用顺序是怎么样的呢?以基类在派生表中声明的顺序为准。所以,对于ying_yang来说,派生表中先声明Bear,然后是Endangered。所以构造函数被调用的顺序是:Bear构造函数(因为Bear是从ZooAnimal派生的,所以在Bear构造函数执行之前,ZooAnimal的构造函数先被调用),Endangered构造函数,然后是Panda构造函数。调用构造函数的路线图是:
ZooAnimal——>Bear——>Endangered——>Panda
拷贝构造函数的调用顺序和构造函数的调用顺序是一样的。因为拷贝构造函数是特殊的构造函数。但是,析构函数的调用顺序总是与构造函数的调用顺序相反。
二、多继承很容易造成二义性
派生类从两个或两个以上的基类中继承同名的成员,即使同名的成员在各自的类中的访问级别不一样(比如,fun()函数在类A的访问级别是public,同名的fun函数在类B的访问级别是private,类C继承了类A和类B,即说明fun函数在类C中是可见的,但是不能直接调用。对于数据成员也是一样的)。然而在这种情况下,直接访问将产生二义性,将导致编译错误。但是,这个编译错误不是由于“对两个成员的非限定修饰访问存在潜在的二义性”所触发的,而是由于“企图真正访问这两个成员”而触发的。例如,如果Bear和Endangered都定义了一个成员函数print(),则如下语句:
ying_yang.print(cout) ;
将导致编译时刻的错误,即使这两个通过继承得到的成员函数定义了不同的参数类型:
Bear::print(ostream&) ;
Endangered::print(ostream&,int) ;
ying_yang.print(cout) ; //同样会导致编译时刻的错误
同样会导致编译时刻的错误。那么,我们应该怎么样解决这个问题呢?有两种解决方案:第一:它是直接访问。那么我们可以改用类域操作符显式的限定修饰“期望被调用的实例”。例如:
//正确,不会导致编译错误
ying_yang.Bear::print(cout) ;
第二:较好的解决方案是Panda类自己解决在继承层次结构中的二义性。最简单的方法是,在提供预期行为的派生类中定义一个同名实例。例如:
inline ostream&Panda::print(ostream&) const
{
Bear::print(os) ;
Endangered::print(os) ;
return os ;
}
三、用派生类对象的地址初始化或赋值基类的指针或引用的注意点
例如,当用Panda对象的地址初始化或赋值Bear或ZooAnimal指针或引用时,Panda接口中“Panda特有的部分”以及“Endangered部分”就不能再被访问。例如:
Bear *pb = new Panda ; //用Panda对象的地址初始化Bear指针pb
pb->print(cout) ; //正确: Panda::print(ostream&)
pb->isA() ; //正确: Bear::isA()
pb->cuddle() ; //错误: 不是Bear接口的部分
pb->highligth() ; //错误: 不是Bear接口的部分
delete pb ; //正确: Panda::~Panda()
类似的,当用Panda类对象的地址初始化或赋值Endangered指针或引用时,Panda接口中“Panda特有的部分”以及“Bear部分”都不能再被访问。例如:
Endangered *pe = new Panda ; //用Panda对象的地址初始化Endangered指针pe
pe->print(cout) ; //正确: Panda::print(ostream&)
pe->isA() ; //错误: 不是Endangered接口的部分
pe->cuddle() ; //错误: 不是Endangered接口的部分
pe->highligth() ; //正确: Endangered::highligth()
delete pe ; //正确: Panda::~Panda()