c 虛函式實現原理簡單剖析

2021-05-09 17:33:58 字數 2435 閱讀 2135

虛函式在c++裡的作用是在是非常非常的大,很多講述c++的文章都會講到它,要用好c++,就一定要學好虛函式。本文對虛函式的一些實現機制,以及c++物件布局做一下探索。

虛函式的作用是實現動態聯編,也就是在程式的執行階段動態地選擇合適的成員函式,在定義了虛函式後,可以在基類的派生類中對虛函式重新定義,在派生類中重 新定義的函式應與虛函式具有相同的形參個數和形參型別。以實現統一的介面,不同定義過程。如果在派生類中沒有對虛函式重新定義,則它繼承其基類的虛函式。 那麼,這個動態聯編是怎麼實現的呢?

下面看乙個簡單例子:

class aa

virtual void fun1()

};class bb :public aa

void ff(){};

};class cc :public aa

void fun()

};首先要明確的是,在有虛函式的類中,有乙個隱藏的成員指標變數vfptr,虛函式的神秘之處就在於這個東西。這是乙個指標,它是指向虛函式表的指標,好啦,又出現了乙個新詞,虛函式表,它就是存放虛函式位址的一張表,(不用關心它的資料結構是咋樣的)。可以通過這個虛函式表找到虛函式的入口位址。ok,名詞解釋完畢.(我有點廢).

總 的說來就是,在有虛函式的類中,一定會有乙個虛函式表指標vfptr,這個vfptr指標會放在類的起始處,虛函式表裡會按基類宣告虛函式的順序在 vfptr裡存放虛函式的位址,虛函式表裡存放的是虛函式的位址,是具體子類的實現函式的位址。呼叫虛函式的時候,是從vfptr所指的函式表裡獲取到函 數字址,然後才呼叫具體的**。

當把乙個繼承類的指標賦值給基類指標時,基類的指標就指向了繼承類的記憶體,此時的vfptr就是繼承類的 vfptr啦。因此,通過基類指標呼叫虛函式的時候就找到的是繼承類的虛函式位址。呼叫的式繼承類的虛函式。如果繼承類沒有過載基類的某個虛函式,如 class bb,則繼承類就是直接繼承的基類的那個虛函式。

ok,下面來看一下類記憶體布局,使用microsoft visual studio的cl命令可以簡單看到類的記憶體布局。

即:使用命令 cl  demo.cpp  /d1reportsingleclasslayoutcc (cc為你想檢視的類名)可檢視類的記憶體布局。

class aa memory layout

class aa size(4):

+---

0      |

+---

aa::$vftable@:

| &a_meta

|  0

0      | &aa::fun

1      | &aa::fun1

aa::fun this adjustor: 0

aa::fun1 this adjustor: 0

class bb memory layout

class bb        size(12):

+---

| +--- (base class

0      | |

| +---

4      | i

8      | j

+---

bb::$vftable@:

| &bb_meta

|  0

0      | &bb::fun

1      | &aa::fun1

bb::fun this adjustor: 0

/class c memory layout

class cc        size(4):

+---

| +--- (base class

0      | |

| +---

+---

cc::$vftable@:

| &cc_meta

|  0

0      | &cc::fun

1      | &cc::fun1

cc::fun1 this adjustor: 0

cc::fun this adjustor: 0

綜上可知,類的虛函式表的結構和其基類的虛函式表結構一致。(順序一致)

如果繼承類沒有過載某個基類的虛函式,

則在繼承類的虛函式表中依然會儲存其基類的那個虛函式的位址。它是直接繼承基類的虛函式。非虛函式不出現在類的記憶體布局裡。

注 意每個類後面的size(*);這個東西。這個是說的是類占用多少記憶體,即使用sizeof(類變數)得到的結果就是這個size。我們來看 看,class aa的size是4,咦,明明該是1(如果沒有虛函式的類中沒有成員變數sizeof結果就是1,不要問我,microsoft visual studio這麼說的)怎麼是4咧,細心的童鞋可能已經發現,剛剛談到了class a還有乙個隱藏的成員指標變數vfptr。因此,class b的size是12就不足為奇了。ok就這樣吧,鄙人不才,有不對之處請各位童鞋多多指正。謝謝

參考: 1. http://c.chinaitlab.com/cc/basic/200908/790967.html

2.以前看過的n多書

C 原理剖析之虛函式表

最近在看c 的一些相關的機制,再加上剛看了陳皓大神的早期關於虛函式表的部落格,便自己動手通過程式設計了解了下虛函式表的原理。c 是通過虛函式來實現多型的的機制。我們可以通過將父類的指標指向子類的例項,如base b new derive 如此一來,如果子類derive中過載了父類中的乙個函式h 那麼...

虛函式的內部實現原理深入剖析

今天學c 多型時,對虛函式實現原理有些疑惑。然後爬了很多文,看了很多教程。經過一系列研究,以下是我的理解 多型是c 物件導向三大特性之一 多型分為兩類 靜態多型和動態多型區別 注意 請按照編號順序檢視 說明 include includeusing namespace std 動物類 class a...

C 虛函式實現原理

c 中的虛函式的作用主要是實現了多型的機制。基類定義虛函式,子類可以重寫該函式。每個類物件新增乙個成員,該成員中儲存了乙個指向函式位址陣列的指標,稱為虛表指標 vptr 該陣列稱為虛函式表 virtual function table,vtbl 即,每個類使用乙個虛函式表,每個類物件用乙個虛表指標。...