一、什麼是多型
多型通俗的來講,就是多種狀態,就是乙個事物在不同條件下表現出的不同狀態。比如出門這件事,受天氣,氣溫不同條件的影響,會表現出不同的狀態,下雨天出門就要打傘,夏天出門就要穿得涼快一點,冬天出門就要穿厚一點。同樣是出門,因外界條件不同,會有多種具體的實現方式。
二、多型的定義及實現
在繼承中要構成多型還有兩個條件:
1. 呼叫函式的物件必須是指標或者引用。
2. 被呼叫的函式必須是虛函式,且完成了虛函式的重寫。
ps:指標的兩種型別:靜態型別-->宣告變數的型別(編譯期間已經確定)
動態型別-->實際指向空間的型別(**執行期間,若構成重寫則會變成動態型別)
//重寫的虛函式的返回值可以不同,但是必須分別是基類指標和派生類指標或者基類
//引用和派生類引用。
#析構函式的重寫問題只要基類中的析構函式為虛函式,就構成了析構函式的重寫,無需與派生類同名。
因為在編譯過程中,析構函式名稱統一被替換為destructor,所以基類中的析構函式最好給成虛函式。
三、多型的原理
①、虛表的介紹及構建過程
論證方法:1.構造繼承方式的場景
2.驗證物件模型
3.驗證虛表的內容(通過所掌握的內容推斷)
從上圖中看出,顯然虛函式比普通成員函式多了乙個叫_vfptr的東西,從名字上看,應該是存放了乙個什麼指標,下面來看看這是什麼指標。
class base
//基類虛函式f1
virtual void func2()//基類虛函式f2
void func3()//基類普通函式f3
private:
int _b = 1;
};class derive : public base
//派生類重寫f1
這個存放虛函式的**,被叫做虛表。
總結一下:
1. 派生類物件d中也有乙個虛表指標,d物件由兩部分構成,一部分是父類繼承下來的成員,虛表指標也就 是存在部分的另一部分是自己的成員。
2. 基類b物件和派生類d物件虛表是不一樣的,這裡我們發現func1完成了重寫,所以d的虛表中存的是重寫的derive::func1,所以虛函式的重寫也叫作覆蓋,覆蓋就是指虛表中虛函式的覆蓋。重寫是語法的叫法,覆蓋是原理層的叫法。
3. 另外func2繼承下來後是虛函式,所以放進了虛表,func3也繼承下來了,但是不是虛函式,所以不會放進虛表。
4. 虛函式表本質是乙個存虛函式指標的指標陣列,這個陣列最後麵放了乙個nullptr。
②、多態函式的呼叫過程
要構成多型的呼叫形式:首先多型的兩個條件都要滿足
引用的哪個類的物件,將來呼叫具體類的虛函式
1.取虛表的位址&vfptr(取物件位址,從物件前四個位元組中取虛表的位址)
2.傳遞this指標
3.從虛表中取將要呼叫虛函式的位址(&vfptr+虛函式在虛表中的偏移量)
4.呼叫該虛函式
③、單繼承、多繼承中的虛表構建規律
單繼承中派生類的虛表構建:a.先將基類中的虛表內容拷貝乙份到派生類虛表中。
b.如果派生類重寫了基 類中某個虛函式,用派生類自己的虛函式覆蓋虛表中基類的虛函式。
c.派生類自己新增加的虛函式按其在 派生類中的宣告次序增加到派生類虛表的最後。
class base1
virtual void func2()
private:
int b1;
};class base2
virtual void func2()
private:
int b2;
};class derive : public base1, public base2
virtual void func3()
private:
int d1;
};
多繼承中派生類的虛表構建:
與單繼承的不同點:多繼承派生類的未重寫的虛函式放在第乙個繼承基類部分的虛函式表中。
以上,繼承與多型的知識點已經大體介紹完畢。還有一些細小的知識點如override,final關鍵字的用法,抽象類生成物件的函式,綜合兩者的菱形繼承和菱形虛擬繼承等,改日重開一貼再議。
如有錯誤、不準確之處,歡迎提議,感激不盡。
C 初階學習 之 繼承與多型(繼承)
作為一門物件導向的程式語言,構造出的許多物件之間存在著眾多關係。如汽車和車輪,是汽車都有車輪,由汽車類可以引出車輪類。賓士和寶馬或者大眾,不同價位對應著不同品牌的汽車,輸入不同的金額呼叫到的則是不同的類。為了描述這些物件間的層次結構和關係,不同條件下對類的的選擇呼叫,這便引出了c 中修飾物件的機制 ...
C 多型 繼承多型
什麼是多型?個人理解為 在程式語言繼承關係中,子類能替代父類,表現出不同的行為。換句話說 在繼承關係中,乙個類被例項化被其子類替代,子類中有父類的虛方法重寫,或者有父類同名方法 new 呼叫相同方法時候,將表現出子類或者父類中不同行為 老闆,上 static void main string arg...
C 繼承與多型
派生類繼承基類 又稱父類 超類 的屬性和方法,在此基礎上可以進行修改或新增新的屬性和方法。class 派生類名 繼承方式 基類名 為了保護基類的資料封裝性,無論哪種繼承方式,積累的私有成員在派生類中都是不可見的。1.public繼承 基類的訪問許可權在派生類中不變。公有還是公有,保護還是保護,派生類...