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

C/C++多態及其實現原理
多態的介紹
多態含義爲一個事物有多種形態。在C ++程序設計中,多態性是指具備不一樣功能的函數能夠用同一個函數名,這樣就能夠用一個函數名調用不一樣內容的函數。通常來講多態分爲兩種:html

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

靜態多態實現
靜態多態靠編譯器來實現,簡單來講就是編譯器對原來的函數名進行修飾。能夠根據函數參數的類型,個數,以及修飾函數const,這就使得函數能夠重載。同理,模板也是能夠實現的,針對不一樣類型的實參來產生對應的特化的函數,經過增長修飾,使得不一樣的類型參數的函數得以區分。函數

動態多態的實現
動態多態靠運行時的類型檢查,從而來進行函數的綁定。聲明一個類時,若是類中有虛方法,則自動在類中增長一個虛函數指針,該指針指向的是一個虛函數表,虛函數表中存着每一個虛函數真正對應的函數地址。動態多態採用一種延遲綁定技術,普通的函數調用,在編譯期間就已經肯定了調用的函數的地址,因此不管怎樣調用,老是那個函數,可是擁有虛函數的類,在調用虛函數時,首先去查虛函數表,而後在肯定調用的是哪個函數,因此,調用的函數是在運行時纔會肯定的。.net

虛表指針初始化問題
當建立子類對象時,編譯器的執行順序實際上是這樣的:設計

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

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

無覆蓋的公有單繼承:虛函數按聲明順序存在於虛表中; 在派生類中,前面是基類的虛函數,後面是派生類的虛函數。
有覆蓋的公有單繼承:先拷貝基類的虛表;若是派生類重寫了基類的虛函數,則修改同位置的基類虛函數;最後面是生類新定義的虛函數。
單繼承的派生類的大小:虛表指針+ 基類的數據成員 + 派生類的成員對象

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

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

菱形繼承


若是派生類有新的虛函數,則添加在第一繼承順序的續表最後面。菱形繼承存在二義性,因爲直接父類都繼承了祖父類的成員變量——致使修改一處,而另一處沒有修改(引發數據不一致性)。

虛繼承中的單繼承
1. 沒有構造函數和析構函數(少中間的0——所佔的字節),派生類有新的虛函數

2. 沒有構造函數和析構函數(少中間的0——所佔的字節),派生類沒有新的虛函數

3. 有構造函數和析構函數(多中間的0——所佔的字節),派生類有新的虛函數

虛繼承中派生類的構造函數作了什麼

虛繼承中的多繼承
  沒有考慮構造函數或析構函數 ,派生類定義了新虛函數

虛繼承中的菱形繼承 沒有考慮構造函數或析構函數 ,派生類定義了新虛函數

相關文章
相關標籤/搜索