多態

多態

一、重寫/覆蓋 

虛函數:可以被重寫的函數,virtual修飾

當派生類繼承基類後,如果基類中含有虛函數,子類可以對虛函數執行重寫(覆蓋),方法是寫一個跟它完全相同的函數(函數名、參數列表、返回值都相同),就會覆蓋掉原來的函數。

覆蓋後,無論用基類指針還是派生類指針,都會調用覆蓋後的函數。

特例:

協變:假如B繼承自A,D繼承自C,那麼A中虛函數返回了C類指針,B中虛函數返回了D類指針,這種情況也構成重寫。

二、虛析構函數:

所有析構函數在底層的函數名都是相同的

***虛析構函數是用來解決子類對象轉化爲父類對象進行析構的問題的。(子父析構函數覆蓋掉父析構函數)

三、final & override

C++11

final:不能被繼承的類或者不能被重寫的虛函數(寫在父類)

override:聲明子類的某個函數必須重寫父類的某個虛函數(子類)

四、重載/重寫/隱藏

重載:針對函數,重名,參數列表不同

重寫/覆蓋:針對繼承,完全相同(協變例外),只在虛函數/純虛函數中存在

隱藏/重定義:針對繼承,重名,不能是虛函數

***重寫是換了一個函數,隱藏是藏一個函數,所以重寫是一個函數,隱藏是兩個函數

五、抽象類:

純虛函數:只有接口,沒有實現的函數。

包含純虛函數的類叫做抽象類,抽象類不能定義對象。

六、虛表:32位4字節 64位8字節

虛表是一個二級函數指針,只要類中包含虛函數,就會在對象的頭部包含一個虛表指針(vfptr)

虛表相當於一個函數指針數組,裏面存放的就是虛函數的地址。

當子類繼承父類時,會繼承虛表,當子類有新的虛函數時,會在虛表後面新增新的項,當子類重寫父類的虛函數時,會把虛表中原有的某一項覆蓋。

七、多重繼承

一個派生類可以來源於多個基類,多個基類間用逗號隔開。

如果多個父類中有重名的成員,那麼會產生二義,必須用父類名::的方式指明用誰的成員。

如果繼承的多個父類中有多個虛表,那麼子類將全部繼承下來。如果子類出現了新的虛函數,那麼會加在第一個虛表(第一個繼承的父類的虛表)的後面,如果多個父類中含有相同的虛函數,子類重寫後,將會只出現一個虛函數。

八、菱形繼承、虛繼承(一般,虛繼承只用在菱形繼承)

菱形繼承:某個類的兩個父類有一個相同的父類。

BC繼承A,C繼承BC.(istream,ostream繼承ios,iostream繼承istream和ostream)

冗餘性:這個類包含了兩份爺爺類

二義性:兩個爺爺長得一樣,分不清

虛繼承:

含有一個虛基類指針(vbptr)指向自己的基類,作用是可以描述自己的父類。當發現被繼承的另一個父類中也有這麼一個相同的虛基類時,兩個基類就會合並,就只保留一個。

普通的繼承只繼承了爺爺的衣鉢,不知道爺爺是誰。虛繼承都知道,所以,發現我的兩個爸爸的爸爸是同一個人的時候,乾脆就只要一個爺爺。

虛繼承可以解決菱形繼承帶來的冗餘性和二義性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章