c 整理 虛函式

2021-08-17 11:03:29 字數 1524 閱讀 2208

解析:簡單的說,虛函式是通過虛函式表實現的,那麼什麼是虛函式表呢?

事實上,如果乙個類中含有虛函式表,則系統會為這個類分配乙個指標成員指向一張虛函式表(vtbl),表中每一項指向乙個虛函式的位址,實際上就是乙個函式指標的陣列。為了說明虛函式表,請看程式:

class parent  

virtual void foo2() {}

void foo3();

};

class child1 : public parent

void foo3();

};

class child2 : public parent

void foo2() {}

void foo3();

};

下面列出了各個類的虛函式表

可以看出,虛函式表既有繼承性,又有多型性。每個派生類的vtbl繼承了它各個基類的vtbl,如果基類vtbl中包含某一項,則其派生類的vtbl中也包含同樣一項,但是兩項的值可能不同。如果派生類覆蓋(override)了該項對應的虛函式,則派生類vtbl的該項指向過載後的虛函式,如果沒有過載的話,則沿用基類的值。

在類物件的記憶體布局中,首先是vtbl指標,然後才是物件的資料。在通過物件指標呼叫乙個虛函式時,編譯器生成的**將先獲取物件類的vtbl指標,然後呼叫vtbl中對應的項。對於通過物件呼叫指標的情況,在編譯期間無法確定指標指向的是基類物件還是派生類物件,或者是哪個派生類物件。但是在執行期間執行到呼叫語句時,這一點已經確定,編譯後的呼叫**能夠根據具體物件獲取正確的vtbl,呼叫正確的虛函式,從而實現多型性。

分析一下這裡的思想所在,問題的實質是這樣,對於發出虛函式呼叫的這個物件指標,在編譯期間缺乏更多的資訊,而在執行期間具備足夠的資訊,但那時已不再進行繫結了,怎麼在二者之間做乙個過渡呢?把繫結所需的資訊用一種通用的資料結構記錄下來,該資料結構可以同物件指標相聯絡,在編譯時只需要使用這個資料結構進行抽象的繫結,而在執行期間將會得到真正的繫結。這個資料結構就是vtbl。可以看到,實現使用者所需的抽象和多型需要進行後繫結,而編譯器又是通過抽象和多型實現後繫結的。

#include using namespace std;  

class a

//構造函式呼叫虛函式

virtual void dosth()

};

class b : public a

};

int main()

{ b b;

return 0;

執行結果是什麼?為什麼?

在建構函式中,虛擬機制不會發生作用,因為基類的建構函式在派生類建構函式之前執行,當基類建構函式執行時,派生類資料成員還沒有被初始化。如果基類建構函式期間呼叫的虛函式向下匹配到派生類,派生類的函式理所應當會涉及本地資料成員,但是那些資料成員還沒有被初始化,而呼叫涉及乙個物件還沒有被初始化的部分自然是危險的,所以c++會提示此路不通。因此,虛函式不會向下匹配到派生類,而是直接執行基類的函式。

結果:i am a 

整理自用 c 繼承 虛函式

一般的認為,虛機制發生在物件呼叫時,其實不然,只要能用到之時,他便會出現!在呼叫基類函式的時候,如果基類呼叫了乙個虛函式,同樣虛機制也會產生效果!不是基類的建構函式中!以下兩端 輸出結果完全不同,原因就在於 呼叫虛函式,只受當前物件的影響。即this指標。include using namespac...

虛函式 純虛函式 虛繼承資料整理

感謝這些優秀的文章 虛函式與純虛函式 虛函式的實現1 虛函式的實現2 菱形繼承與虛繼承 首先從虛函式開始說起吧.虛函式是實現了多型機制,具體表現為父型別的指標指向其子類的例項.然後通過服淚指標嗲用實際子類中的成員函式.這種技術可以讓父類指標有多種形態.如果呼叫非虛函式,無論物件是什麼型別,都執行基類...

C 虛函式 純虛函式

1 基本概念 虛函式是在基類中使用關鍵字virtual宣告的函式。在派生類中重新定義基類中定義的虛函式時,會告訴編譯器不要靜態鏈結到該函式。我們想要的是在程式中任意點可以根據所呼叫的物件型別來選擇呼叫的函式,這種操作被稱為動態鏈結,或後期繫結。您可能想要在基類中定義虛函式,以便在派生類中重新定義該函...