轉(zhuǎn)載內(nèi)容。另有其他更好的轉(zhuǎn)載參考資料,在博文最末尾。
面向?qū)ο缶幊陶Z言中的多重繼承指的是一個(gè)類別可以同時(shí)從多于一個(gè)父類繼承行為與特征的功能。與單一繼承相對,單一繼承指一個(gè)類別只可以繼承自一個(gè)父類。 重溫Java,發(fā)現(xiàn)Java竟然不支持類多重繼承(直接繼承類),卻允許接口的多重繼承。。
C++中類可以多重繼承,Java中為什么不實(shí)現(xiàn)這個(gè)功能呢?多重繼承會帶來哪些問題,從而導(dǎo)致Java放棄類的多重繼承?
再一深究,發(fā)現(xiàn)多年以來,多重繼承一直是個(gè)敏感話題,贊成者看到的是免去笨拙的混合繼承的利處,反對者看到的是多處混淆的弊端,例如變量的二義性,并且是多個(gè)變量。所以關(guān)于它的好處與風(fēng)險(xiǎn)之間孰輕孰重成為OO界多年?duì)幷摰慕裹c(diǎn)。
其實(shí)最大的問題是出現(xiàn)拓補(bǔ)圖,也就是出現(xiàn)鉆石型繼承結(jié)構(gòu)(DOD),個(gè)人感覺這是個(gè)致命傷。正如其名:Diamond of Death。
比如一個(gè)基類:動物。它有三個(gè)派生類:哺乳類動物,卡通類動物,寵物(確實(shí)都形成ISA關(guān)系)。現(xiàn)在有一個(gè)子類貓,從關(guān)系上推,它可以繼承自哺乳類,卡通類,寵物,都符合ISA,如果要體現(xiàn)所有的特性,就需要全部繼承,這樣就形成了多重繼承,卻也形成了DOD,這樣以后問題就出現(xiàn)了,從貓到動物的繼承有三條路徑,如果哺乳類,卡通類與寵物類中有相同的成員函數(shù)或變量,這樣的數(shù)據(jù)組織方式會形成多義。
C++怎么解決這個(gè)問題的呢?虛繼承。結(jié)果就是不得不犧牲一些內(nèi)存開銷,因?yàn)橐粋€(gè)功能要在多處被重寫。并且函數(shù)表里的函數(shù)指針必須調(diào)整,這樣即使可以滿足功能,在后期的維護(hù)也很復(fù)雜。
所以,Java才會采用這樣折中的方法,硬生生的將類多重繼承題了出去。
并且,網(wǎng)上也有不少建議,要盡可能避免多重繼承,不惜一切代價(jià)去避免鉆石結(jié)構(gòu),以避免后期不可挽回的大返工。
多重繼承的概念:C++允許為一個(gè)派生類指定多個(gè)基類,這樣的繼承結(jié)構(gòu)被稱做多重繼承。
舉個(gè)例子,交通工具類可以派生出汽車和船連個(gè)子類,但擁有汽車和船共同特性水陸兩用汽車就必須繼承來自汽車類與船類的共同屬性。
由此我們不難想出如下的圖例與代碼:
面向?qū)ο缶幊陶Z言中的多重繼承指的是一個(gè)類別可以同時(shí)從多于一個(gè)父類繼承行為與特征的功能。與單一繼承相對,單一繼承指一個(gè)類別只可以繼承自一個(gè)父類。
舉個(gè)簡單的例子:
由此我們不難想出如下的圖例與代碼:
當(dāng)一個(gè)派生類要使用多重繼承的時(shí)候,必須在派生類名和冒號之后列出所有基類的類名,并用逗好分隔。
//程序作者:管寧
//站點(diǎn):www.cndev-lab.com
//所有稿件均有版權(quán),如要轉(zhuǎn)載,請務(wù)必著名出處和作者
#include
using
class
{
};
class
{