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的專欄