多继承

        为支持多继承,一个类的派生表被扩展成支持逗号分割的基类表。例如:

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()


 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值