C 多型性 虛函式的呼叫原理

2021-04-30 14:22:02 字數 1673 閱讀 2805

c++多型性:虛函式的呼叫原理

多型性給我們帶來了好處:多型使得我們可以通過基類的引用或指標來指明乙個物件(包含其派生類的物件),當呼叫函式時可以自動判斷呼叫的是哪個物件的函式。

乙個函式說明為虛函式,表明在繼承的類中過載這個函式時,當呼叫這個函式時應當檢視以確定呼叫哪個物件的這個函式。

普通函式的處理:乙個特定的函式都會對映到特定的**,無論時編譯階段還是連線階段,編譯器都能計算出這個函式的位址,呼叫即可。

虛函式的處理:被呼叫的函式不僅依據呼叫的特定函式,還依據呼叫的物件的種類。通常是由虛函式表(vtable)來實現的。

虛函式表的結構:它是乙個函式指標表,每乙個表項都指向乙個函式。任何乙個包含至少乙個虛函式的類都會有這樣一張表。需要注意的是vtable只包含虛函式的指標,沒有函式體。實現上是乙個函式指標的陣列。虛函式表既有繼承性又有多型性。每個派生類的vtable繼承了它各個基類的vtable,如果基類vtable中包含某一項,則其派生類的vtable中也將包含同樣的一項,但是兩項的值可能不同。如果派生類過載(override)了該項對應的虛函式,則派生類vtable的該項指向過載後的虛函式,沒有過載的話,則沿用基類的值。

每乙個類只有唯一的乙個vtable,不是每個物件都有乙個vtable,恰恰是每個同乙個類的物件都有乙個指標,這個指標指向該類的vtable(當然,前提是這個類包含虛函式)。那麼,每個物件只額外增加了乙個指標的大小,一般說來是4位元組。

在類物件的記憶體布局中,首先是該類的vtable指標,然後才是物件資料。

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

給出例項**:

class a

}class b :public a

}int f (a *pa)

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

下面是通過基類的指標來呼叫虛函式時,所發生的一切:

step 1:開始執行呼叫 pa->run();(這裡能判斷到底是哪個物件)

step 2:取得物件的vtable的指標

step 3:從vtable那裡獲得函式入口的偏移量,即得到要呼叫的函式的指標

step 4:根據vtable的位址找到函式,並呼叫函式。

step 1和step 4對於一般函式是一樣的,虛函式只是多了step 2和step 3。

解惑:1基類和派生類是共用一表,還是各有各的表(物理上)

答:基類和派生類是各有各的表,也就是說他們的實體地址是分開的,基類和派生類的虛表的唯一關聯是:當派生類沒有實現基類虛函式的過載時,派生類會直接把自己表的該函式位址值寫為基類的該函式位址值.

C 多型性 虛函式的呼叫原理

多型性給我們帶來了好處 多型使得我們可以通過基類的引用或指標來指明乙個物件 包含其派生類的物件 當呼叫函式時可以自動判斷呼叫的是哪個物件的函式。乙個函式說明為虛函式,表明在繼承的類中過載這個函式時,當呼叫這個函式時應當檢視以確定呼叫哪個物件的這個函式。普通函式的處理 乙個特定的函式都會對映到特定的 ...

c 多型性 虛函式

c 中多型性是指通過用virtual關鍵字來繫結同名同引數的函式,實現在編譯中進行後繫結,即在編譯過程中不繫結類,在執行時與具體的物件進行繫結,這樣就可以動態地與實際聯絡 比如乙個類 animal 有乙個虛函式breath 魚類 fish 也有函式breath 狗類 dog 函式breath 具體呼...

c 多型性 虛函式

虛函式與純虛函式的區別 1 擁有虛函式的類可以宣告物件,但擁有純虛函式的類不可以宣告物件 只能宣告乙個指標,並且不能給其分配記憶體 並且將這個類稱為抽象類 特點 1 虛函式是動態繫結的基礎。2 是非靜態的成員函式。在類的宣告中,在函式原型之前寫virtual。不能宣告為靜態函式 3 virtual ...