蔣麗苑,C 虛成員函式表vtable

2021-10-14 18:39:55 字數 1250 閱讀 4996

通過前兩節的介紹,想必對多型有一定的了解了。這一節將介紹多型是如何實現的,關於如何實現多型,對於程式設計人員來說即使不知道也是完全沒有關係的,但是對於加深對多型的理解具有重要意義,故而在此節中稍微闡述一下多型的實現機制。

在c++中通過虛成員函式表vtable實現多型,虛函式表中儲存的是類中虛函式的入口位址。在普通的類中是沒有虛函式表的,只有在具有虛函式的類中(無論是自身新增的虛函式還是繼承過來的虛函式)才會具有虛函式表,通常虛成員函式表的首位址將會被存入物件的最前面(在32位的作業系統中,儲存位址是用4個位元組,因此這個首位址就會占用物件的前四個位元組的空間)。

例1:#include

using namespace std;

class base

virtual void v2()

};class derived: public base

virtual void v2()

};int main()

我們將兩個類定義成例1所示形式,兩個類中各有兩個虛函式v1和v2,我們將其函式入口位址找到列於下表中:

虛成員函式 函式入口位址 虛成員函式 函式入口位址

base::v1 00d15834 derived::v1 00d15844

base::v2 00d15838 derived::v2 00d15848

虛函式表裡面儲存的就是虛函式的入口位址。我們再來看主函式,在主函式中先定義了base類物件b,因為b類中有虛函式,因此存在虛函式表,而虛函式表的首位址就儲存在物件所在儲存空間的最前,具體情況可以見下圖。當然宣告derived物件d之後,情況也跟下圖中一樣,同樣在物件儲存空間中包含虛成員函式表位址。

之後定義了乙個基類型別的指標p,當我們通過基類指標p呼叫虛函式v1或v2時,系統會先去p所指向的物件的前四個位元組中尋找到虛函式表位址,之後在記憶體中找到該虛函式表,然後在表中找到對應函式的入口位址,之後直接訪問這個函式了。當p指標指向的是基類物件時,基類的虛函式表將會被訪問,基類中虛函式將會被呼叫。當p指標指向的是派生類物件,則訪問的是派生類的虛函式表,派生類的虛函式表中存的是派生類中的虛函式入口位址,因此呼叫的是派生類中的虛函式。

使用多型會降低程式執行效率,使用多型的程式會使用更多的儲存空間,儲存虛函式表等內容,而且在呼叫函式時需要去虛函式表中查詢函式入口位址,這會增加程式執行時間。在設計程式時,程式設計人員可以選擇性的使用多型,對於有需要的函式使用多型,對於其它的函式則不要採用多型。通常情況下,如果乙個類需要作為基類,並且期望在派生類中修改某成員函式的功能,並且在使用類物件的時候會採用指標或引用的形式訪問該函式,則將該函式宣告為虛函式。

蔣麗苑,C語言位域(位段)詳解

在結構體定義時,我們可以指定某個成員變數所占用的二進位制位數 bit 這就是位域。請看下面的例子 struct bs 後面的數字用來限定成員變數占用的位數。成員 m 沒有限制,根據資料型別即可推算出它占用 4 個位元組 byte 的記憶體。成員 n ch 被 後面的數字限制,不能再根據資料型別計算長...

C 虛函式表

考慮最簡單的有虛函式的繼承關係 class f class s public f 此時,我們可以定義乙個父類的指標,實際指向乙個子類的物件。呼叫func函式的結果是子類的函式。虛函式在這裡是動態繫結的。f f new s f func 輸出s func 我們知道子類即使不定義虛函式也會繼承該虛函式表...

C 虛函式表

一般來說,對於開發者我們只需要知道虛函式的使用方法,以及虛函式表的存在即可。但面試時往往會遇到更細節的問題,比如讓你實現乙個虛函式機制,雖然不太實用,總歸了解些底層知識也是件好事。但如果有人苦苦相逼一定要拿這個刷人,你就去罵他吧,你才是寫編譯器的,你們全家都是寫編譯器的。唉,我有些失態了.1.虛函式...