轉載內容。另有其他更好的轉載參考資料,在博文最末尾。
面向對象編程語言中的多重繼承指的是一個類別可以同時從多于一個父類繼承行為與特征的功能。與單一繼承相對,單一繼承指一個類別只可以繼承自一個父類。
重溫Java,發現Java竟然不支持類多重繼承(直接繼承類),卻允許接口的多重繼承。。
C++中類可以多重繼承,Java中為什么不實現這個功能呢?多重繼承會帶來哪些問題,從而導致Java放棄類的多重繼承?
再一深究,發現多年以來,多重繼承一直是個敏感話題,贊成者看到的是免去笨拙的混合繼承的利處,反對者看到的是多處混淆的弊端,例如變量的二義性,并且是多個變量。所以關于它的好處與風險之間孰輕孰重成為OO界多年爭論的焦點。
其實最大的問題是出現拓補圖,也就是出現鉆石型繼承結構(DOD),個人感覺這是個致命傷。正如其名:Diamond of Death。
舉個簡單的例子:
比如一個基類:動物。它有三個派生類:哺乳類動物,卡通類動物,寵物(確實都形成ISA關系)。現在有一個子類貓,從關系上推,它可以繼承自哺乳類,卡通類,寵物,都符合ISA,如果要體現所有的特性,就需要全部繼承,這樣就形成了多重繼承,卻也形成了DOD,這樣以后問題就出現了,從貓到動物的繼承有三條路徑,如果哺乳類,卡通類與寵物類中有相同的成員函數或變量,這樣的數據組織方式會形成多義。
C++怎么解決這個問題的呢?虛繼承。結果就是不得不犧牲一些內存開銷,因為一個功能要在多處被重寫。并且函數表里的函數指針必須調整,這樣即使可以滿足功能,在后期的維護也很復雜。
所以,Java才會采用這樣折中的方法,硬生生的將類多重繼承題了出去。
并且,網上也有不少建議,要盡可能避免多重繼承,不惜一切代價去避免鉆石結構,以避免后期不可挽回的大返工。
多重繼承的概念:C++允許為一個派生類指定多個基類,這樣的繼承結構被稱做多重繼承。
舉個例子,交通工具類可以派生出汽車和船連個子類,但擁有汽車和船共同特性水陸兩用汽車就必須繼承來自汽車類與船類的共同屬性。
由此我們不難想出如下的圖例與代碼:

當一個派生類要使用多重繼承的時候,必須在派生類名和冒號之后列出所有基類的類名,并用逗好分隔。
//程序作者:管寧
//站點:www.cndev-lab.com
//所有稿件均有版權,如要轉載,請務必著名出處和作者
#include <iostream>
using namespace std;
class Vehicle
{
public:
Vehicle(int weight = 0)
{
Vehicle::weight = weight;
}
void SetWeight(int weight)
{
cout<<"重新設置重量"<<endl;
Vehicle::weight = weight;
}
virtual void ShowMe() = 0;
protected:
int weight;
};
class Car:public Vehicle//汽車
{
public:
Car(int weight=0,int aird=0):Vehicle(weight)
{
Car::aird = aird;
}
void ShowMe()
{
cout<<"我是汽車!"<<endl;