第17章 用于大型程序的工具(14)
17.3.2 转换与多个基类
在单个基类情况下,派生类的指针或引用可以自动转换为基类的指针或引用,对于多重继承也是如此,派生类的指针或引用可以转换为其任意基类的指针或引用。
在多重继承情况下,遇到二义性转换的可能性更大。编译器不会试图根据派生类转换来区别基类间的转换,转换带每个基类都一样好。
namespace Andersoft
{
namespace Animal
{
class ZooAnimal{};
class Endangered{};
class Bear:public ZooAnimal{};
class Panda:public Bear,public Endangered{
public:
Panda():Bear(),Endangered(){}
};
}
}
namespace Andersoft
{
namespace Animal
{
class ZooAnimal{};
class Endangered{};
class Bear:public ZooAnimal{};
class Panda:public Bear,public Endangered{
public:
Panda():Bear(),Endangered(){}
};
}
}
using namespace Andersoft::Animal;
int _tmain(int argc, _TCHAR* argv[])
{
ZooAnimal *za=new Panda();
Endangered ea=Panda();
Panda pa=Panda();
Bear &ba=pa;
return 0;
}
using namespace Andersoft::Animal;
int _tmain(int argc, _TCHAR* argv[])
{
ZooAnimal *za=new Panda();
Endangered ea=Panda();
Panda pa=Panda();
Bear &ba=pa;
return 0;
}
1. 多重继承下的虚函数
2. 基于指针类型或引用类型的查找
像单继承一样,用基类的指针或引用只能访问基类中定义(或继承)的成员,不能访问派生类中引入的成员。
当一个类继承于多个基类的时候,那些基类之间没有隐含的关系,不允许使用一个基类的指针访问其他基类的成员。
3. 确定使用哪个析构函数
假定所有根基类都将它们的析构函数适当定义为虚函数,那么,无论通过哪种指针类型删除对象,虚析构函数的处理都是一致的。
假定这些指针每个都指向子类对象,则每种情况下发生完全相同的析构函数调用次序。析构函数调用的次序是构造函数次序的逆序。
ZooAnimal *za=new Panda();
delete za; //execute ~Panda -> ~Endangered -> ~Bear
ZooAnimal *za=new Panda();
delete za; //execute ~Panda -> ~Endangered -> ~Bear17.3.3 多重继承派生类的复制控制
多重继承的派生类的逐个成员初始化、赋值和析构,表现得与单继承下的一样,使用基类自己的复制构造函数、赋值操作符或析构函数隐式构造、赋值或撤销每个基类。
合成的赋值操作符的行为类似于复制构造函数。
合成的析构函数撤销子类对象的每个成员,并且按构造函数次序的逆序为基类部分调用析构函数。
像单继承的情况一样,如果具有多个基类的类定义了自己的析构函数,该析构函数只负责清除派生类。如果派生类定义了自己的复制构造函数或赋值操作符,则类负责复制(赋值)所有的基类子部分。只有派生类使用复制构造函数或赋值操作符的合成版本,才自动复制或赋值基类部分。
17.3.4 多重继承下的类作用域
当一个类有多个基类的时候,通过所有直接基类同时进行名字查找。多重继承的派生类有可能从两个或多个基类继承同名成员,对该成员不加限定的使用是二义性的。
1. 多个基类可能导致二义性。
2. 首先发生名字查找
即使两个继承的函数有不同的形参表,也会发生错误。类似地,即使函数在一个类中是私有的而在另一个类中是公有或受保护的,也是错误的。
3. 避免用户级二义性
可以通过指定使用哪个类解决二义性。
避免潜在二义性最好的方法是,在解决二义性的派生类中定义函数的一个版本。
namespace Andersoft
{
namespace Animal
{
class ZooAnimal{
public:
void Print(){}
};
class Endangered{
public:
void Print(){}
};
class Bear:public ZooAnimal{
public:
void Print(){
ZooAnimal::Print();
}
};
class Panda:public Bear,public Endangered{
public:
Panda():Bear(),Endangered(){}
void Print(){
Bear::Print();
Endangered::Print();
}
};
}
}
namespace Andersoft
{
namespace Animal
{
class ZooAnimal{
public:
void Print(){}
};
class Endangered{
public:
void Print(){}
};
class Bear:public ZooAnimal{
public:
void Print(){
ZooAnimal::Print();
}
};
class Panda:public Bear,public Endangered{
public:
Panda():Bear(),Endangered(){}
void Print(){
Bear::Print();
Endangered::Print();
}
};
}
}Panda *za=new Panda();
za->Endangered::Print();
za->Print();
摘自 xufei96的专栏
补充:软件开发 , C++ ,