1. 程式人生 > >C/C++多型及其實現原理

C/C++多型及其實現原理

開發十年,就只剩下這套架構體系了! >>>   

C/C++多型及其實現原理
多型的介紹
多型含義為一個事物有多種形態。在C ++程式設計中,多型性是指具有不同功能的函式可以用同一個函式名,這樣就可以用一個函式名呼叫不同內容的函式。一般來說多型分為兩種:

靜態多型:也稱為編譯時多型,主要包括引數多型,過載多型和強制多型。引數多型:採用引數化模板,通過給出不同的型別引數,使得一個結構有多種型別。如 C++語言中的函式模板和類模板屬於引數多型。引數多型又叫靜態多型,它的執行速度快,異常少,呼叫在編譯時已經確定。過載多型:同一個名字在不同的上下文中所代表的含義不同。典型的例子是運算子過載和函式過載。強制多型:編譯程式通過語義操作,把操作物件的型別強行加以變換,以符合函式或操作符的要求。程式設計語言中基本型別的大多數操作符,在發生不同型別的資料進行混合運算時,編譯程式一般都會進行強制多型。程式設計師也可以顯示地進行強制多型的操作。如 int+double,編譯系統一般會把 int 轉換為 double,然後執行 double+double 運算,這個int->double 的轉換,就實現了強制多型,即可是隱式的,也可顯式轉換。強制多型屬於靜態多型。
 
動態多型:也稱執行時多型,主要包括:包含多型。包含多型的基礎是虛擬函式。主要是通過類的繼承和虛擬函式來實現,當基類和子類擁有同名同參同返回的方法,且該方法宣告為虛方法,當基類物件,指標,引用指向的是派生類的物件的時候,基類物件,指標,引用在呼叫基類的方法,實際上呼叫的是派生類方法。
過載多型和強制多型是指特定多型, 過載多型和強制多型稱為特殊多型性,用來刻畫語義上無關聯的型別間的關係;引數多型和包含多型是指通用多型,型別引數化多型和包含多型稱為一般多型性,用來系統地刻畫語義上相關的一組型別。

靜態多型實現
靜態多型靠編譯器來實現,簡單來說就是編譯器對原來的函式名進行修飾。可以根據函式引數的型別,個數,以及修飾函式const,這就使得函式可以過載。同理,模板也是可以實現的,針對不同型別的實參來產生對應的特化的函式,通過增加修飾,使得不同的型別引數的函式得以區分。

動態多型的實現
動態多型靠執行時的型別檢查,從而來進行函式的繫結。宣告一個類時,如果類中有虛方法,則自動在類中增加一個虛擬函式指標,該指標指向的是一個虛擬函式表,虛擬函式表中存著每個虛擬函式真正對應的函式地址。動態多型採用一種延遲繫結技術,普通的函式呼叫,在編譯期間就已經確定了呼叫的函式的地址,所以無論怎樣呼叫,總是那個函式,但是擁有虛擬函式的類,在呼叫虛擬函式時,首先去查虛擬函式表,然後在確定呼叫的是哪一個函式,所以,呼叫的函式是在執行時才會確定的。

虛表指標初始化問題
當建立子類物件時,編譯器的執行順序其實是這樣的:

物件在建立時,由編譯器對 vptr 進行初始化
子類的構造會先呼叫父類的建構函式,這個時候 vptr 會先指向父類的虛擬函式表
子類構造的時候,vptr 會再指向子類的虛擬函式表
物件的建立完成後,vptr 最終的指向才確定
虛擬函式表的構成
具體的詳細細節見https://blog.csdn.net/wenqiang1208/article/details/53148486

https://www.cnblogs.com/longcnblogs/archive/2017/10/09/7642951.html

無覆蓋的公有單繼承:虛擬函式按宣告順序存在於虛表中; 在派生類中,前面是基類的虛擬函式,後面是派生類的虛擬函式。
有覆蓋的公有單繼承:先拷貝基類的虛表;如果派生類重寫了基類的虛擬函式,則修改同位置的基類虛擬函式;最後面是生類新定義的虛擬函式。
單繼承的派生類的大小:虛表指標+ 基類的資料成員 + 派生類的成員

多重繼承:
多重繼承派生類的大小:(例如有兩個父類)——基類1的虛表指標+基類1的成員變數+基類2的虛表指標+基類2的成員變數+子類成員變數

如果派生類有新定義的虛擬函式,則存放在繼承順序第一的基類續表的最後面。

菱形繼承


如果派生類有新的虛擬函式,則新增在第一繼承順序的續表最後面。菱形繼承存在二義性,由於直接父類都繼承了祖父類的成員變數——導致修改一處,而另外一處沒有修改(引起資料不一致性)。

虛繼承中的單繼承
1. 沒有建構函式和解構函式(少中間的0——所佔的位元組),派生類有新的虛擬函式

2. 沒有建構函式和解構函式(少中間的0——所佔的位元組),派生類沒有新的虛擬函式

3. 有建構函式和解構函式(多中間的0——所佔的位元組),派生類有新的虛擬函式

虛繼承中派生類的建構函式做了什麼

虛繼承中的多繼承
  沒有考慮建構函式或解構函式 ,派生類定義了新虛擬函式

虛繼承中的菱形繼承
沒有考慮建構函式或解構函式 ,派生類定義了新虛擬函式

 
--------------------- 
作者:hycxag 
來源:CSDN 
原文:https://blog.csdn.net/hycxag/article/details/82978173 
版權宣告:本文為博主原創文章,轉載請