C 多型 靜態多型與動態多型

2021-07-27 01:56:39 字數 1939 閱讀 8879

多型: 顧名思義,多型就是多種形態,也就是對不同物件傳送同乙個訊息,不同物件會做出不同的響應。

並且多型分為靜態多型和動態多型。

靜態多型就是在系統編譯期間就可以確定程式執行到這裡將要執行哪個函式,例如:函式的過載,物件名加點操作符執行成員函式等,都是靜態多型,其中,過載是在形成符號表的時候,對函式名做了區分,從而確定了程式執行到這裡將要執行哪個函式,物件名加點操作符執行成員函式是通過this指標來呼叫的。

函式的過載比較簡單,不再贅述,這裡我們通過乙個簡單的例子來看一下物件名加點操作符執行成員函式的靜態多型:

class a

public:

int _a;

};int main()

這裡定義了乙個a類,有乙個成員函式和乙個成員,我們將程式的部分彙編**擷取出來如下圖:

我們可以看到這裡直接是乙個lea指令將a1物件的位址放入暫存器eax中,也就是物件的this指標,然後用call指令就可以跳轉到set函式,也就是說其彙編**在此時就知道應該要去到哪個地方之行哪個函式,這就是靜態多型,也叫編譯時多型

動態多型則是利用虛函式實現了執行時的多型,也就是說在系統編譯的時候並不知道程式將要呼叫哪乙個函式,只有在執行到這裡的時候才能確定接下來會跳轉到哪乙個函式的棧幀。

在說動態多型之前我們先來看一下什麼是虛函式,虛函式就是在基類中宣告該函式是虛擬的(在函式之前加virtual關鍵字),然後在子類中正式的定義(子類中的該函式的函式名,返回值,函式引數個數,引數型別,全都與基類的所宣告的虛函式相同,此時才能稱為重寫,才符合虛函式,否則就是函式的過載),再定義乙個指向基類物件的指標,然後使該指標指向由該基類派生的子類物件,再然後用這個指標來呼叫改虛函式,就能實現動態多型。

下面我們通過乙個例子來看一下利用虛函式實現的動態多型:

class a

virtual void get()

public:

int _a;

};class b : public a

void get()

int _b;

};int main()

在這裡我們看到,基類a的get函式宣告為虛函式,在b類中進行了重寫,

然後在main函式中分別用基類的ptr1和指向子類的ptr2進行呼叫虛函式get,我們得到了如下圖的輸出:

這說明確實是實現了不同呼叫,而且是在執行時,那麼虛函式的底層到底是怎麼實現的呢,我們來看一下彙編**及其物件模型

通過上圖的彙編**,我們看到這裡做了一系列的指標解引用處理,最後確定了eax中應該存放的this指標的值,要搞清楚這個必須要搞清楚子類的物件模型。

用監視視窗檢視b1可以看到如上圖所示,這裡的_vfptr是乙個虛表指標,它指向乙個存放該類物件的所有虛函式的位址的表,我們可以將該錶理解為乙個函式指標陣列,在該陣列的最後乙個元素,編譯系統會將其置為0,。

物件模型如下圖示:

其中紅色為a類的成員,黑色為b類物件b1的成員,紫色就是乙個虛函式表,存放著存放該類物件的所有虛函式的位址,彙編**做了一系列的指標解引用處理就是為了從虛函式表中找到相應的虛函式進行呼叫,從而實現了動態多型。

C 靜態多型與動態多型

多型按字面的意思就是多種形態,相同的方法呼叫,但是有不同的實現方式。多型性可以簡單地概括為 乙個介面,多種方法 c 有兩種多型形式 靜態多型 也稱為編譯期間的多型,編譯器在編譯期間完成的,編譯器根據函式實參的型別 可能會進行隱式型別轉換 可推斷出要呼叫那個函式,如果有對應的函式就呼叫該函式,否則出現...

C 動態多型與靜態多型

c 中有兩種多型 動多型 執行期多型 和靜多型 編譯期多型 而靜多型主要通過模板來實現,巨集也是實現靜多型的一種途徑。模板不採用虛函式機制,所以所有呼叫在編譯期就可確定,因此它是靜態的。基於繼承和虛函式,多型的設計思想主要在於 對於幾個相關物件的型別,確定它們之間的乙個共同功能集 然後在基類中,把這...

靜態多型 動態多型

又稱編譯期多型,即在系統編譯期間就可以確定程式將要執行哪個函式。例如 函式過載,通過類成員運算子指定的運算。函式過載示例 class a a int x void f void f int x class b void f void f int x 以上,類a中兩個a 是函式過載,兩個f 是函式過載...