C 多型實現機制剖析

2021-10-14 19:56:38 字數 2094 閱讀 4363

物件導向的三大概念:封裝,繼承,多型。

封裝突破了c語言函式的概念;繼承實現了**的復用,那麼多型實現了什麼價值呢,簡單理解就是前人寫的**(框架)可以呼叫後人寫的**。

多型性可以簡單的概括為「1個介面,多種方法」,在程式執行的過程中才決定呼叫的機制

程式實現上是這樣:通過父類指標呼叫子類的函式,可以讓父類指標有多種形態。

多型的單個條件:1.要有繼承。2. 要有虛函式重寫。3.要有父類指標(引用)指向子類物件。

我們先從乙個例子來**

#include class animal

答案是輸出:animal breathe

結果分析:

那麼為了得到我們想要的結果,就要使用虛函式

前面輸出的結果是因為編譯器在編譯的時候,就已經確定了物件呼叫的函式的位址,要解決這個問題就要使用遲繫結(late binding)技術。當編譯器使用遲繫結時,就會在執行時再去確定物件的型別以及正確的呼叫函式。而要讓編譯器採用遲繫結,就要在基類中宣告函式時使用virtual關鍵字(注意,這是必須的,很多學員就是因為沒有使用虛函式而寫出很多錯誤的例子),這樣的函式我們稱為虛函式。一旦某個函式在基類中宣告為virtual,那麼在所有的派生類中該函式都是virtual,而不需要再顯式地宣告為virtual。

下面我們將上面一段**進行部分修改

virtual void breathe()

};則sizeof(a)=1;

如果改為如下:

class a

void g()

}

則sizeof(a)=4! 這是因為在類a中存在virtual function,為了實現多型,每個含有virtual function的類中都隱式包含著乙個靜態虛指標vfptr指向該類的靜態虛表vtable, vtable中的表項指向類中的每個virtual function的入口位址

例如 我們declare 乙個a型別的object :

a c;

a d;

則編譯後其記憶體分布如下:

轉存失敗

重新上傳

取消從 vfptr所指向的vtable可以看出,每個virtual function都占有乙個entry,例如本例中的f函式。而g函式因為不是virtual型別,故不在vtable的表項之內。說明:vtab屬於類成員靜態pointer,而vfptr屬於物件pointer

public b:public a

};

a c;

a d;

b e;

編譯後,其記憶體分布如下:

轉存失敗

重新上傳

取消從中我們可以看出,b型別的物件e有乙個vfptr指向vtable address:0x00400030 ,而a型別的物件c和d共同指向類的vtable address:0x00400050a

轉存失敗

重新上傳

取消可以看出,此時pc指向類b的虛表位址,從而呼叫物件e的方法。

繼續執行,當執行至pc=&c時候,此時pc的vptr值為0x00420050,即指向類a的vtable位址,從而呼叫c的方法。

這就是動態繫結!(dynamic binding)或者叫做遲後聯編(lazy compile)。

總結:

對於虛函式呼叫來說,每乙個物件內部都有乙個虛表指標,該虛表指標被初始化為本類的虛表。所以在程式中,不管你的物件型別如何轉換,但該物件內部的虛表指標是固定的,所以呢,才能實現動態的物件函式呼叫,這就是c++多型性實現的原理。

需要注意的幾點

總結(基類有虛函式):

1、每乙個類都有虛表。

2、虛表可以繼承,如果子類沒有重寫虛函式,那麼子類虛表中仍然會有該函式的位址,只不過這個位址指向的是基類的虛函式實現。如果基類3個虛函式,那麼基類的虛表中就有三項(虛函式位址),派生類也會有虛表,至少有三項,如果重寫了相應的虛函式,那麼虛表中的位址就會改變,指向自身的虛函式實現。如果派生類有自己的虛函式,那麼虛表中就會新增該項。

3、派生類的虛表中虛函式位址的排列順序和基類的虛表中虛函式位址排列順序相同。

C 多型實現機制剖析

物件導向的三大概念 封裝,繼承,多型。封裝突破了c語言函式的概念 繼承實現了 的復用,那麼多型實現了什麼價值呢,簡單理解就是前人寫的 框架 可以呼叫後人寫的 1 什麼是多型?多型性可以簡單的概括為 1個介面,多種方法 在程式執行的過程中才決定呼叫的機制 程式實現上是這樣 通過父類指標呼叫子類的函式,...

C 的多型性實現機制剖析

c 的多型性實現機制剖析 即 vc this 指標詳細說明 2006年1 月12日星期四 我們先看乙個例子 例 1 1 include class animal void breathe class fish public animal void main 注意,在例 1 1的程式中沒有定義虛函式。...

C 的多型性實現機制剖析

1 多型性和虛函式 我們先看乙個例子 考慮一下這段程式的輸出結果是什麼?答案是輸出 animal breath 我們在main函式中首先定義乙個fish類的物件fh,接著定義了乙個指向animal類的指標pan,將fn的位址賦給了指標變數pan,然後利用該變數呼叫pan breath 許多人往往將這...