動態聯編學習 三 虛函式表VTABLE

2021-04-24 19:12:55 字數 1774 閱讀 2199

編譯器在執行過程中遇到

virtual

關鍵字的時候,將自動安裝動態

聯編需要

的機制,首先為這些包含

virtual

函式的類(注意不是類的例項)

--即使是祖先類包含虛函式而本身沒有

--建立一張虛函式表

vtable

。在這些虛函式表中,編譯器將依次按照函式宣告次序放置類的特定虛函式的位址。同時在每個帶有虛函式的類中放置乙個稱之為

vpointer

的指標,簡稱

vptr

,這個指標指向這個類的

vtable。

關於虛函式表,有幾點必須宣告清楚:

1. 每乙個類別只能有乙個虛函式表,如果該類沒有虛函式,則不存在虛函式表。

2. c++

編譯時候編譯器會在含有虛函式的類中加上乙個指向虛函式表的指標

vptr。

3. 從乙個類別誕生的每乙個物件,將獲取該類別中的

vptr

指標,這個指標同樣指向類的

vtable。

因此類、物件、

vtable

的層次結構可以用下圖表示。其中x類和

y類的物件的指標都指向了

x,y的虛函式表,同時

x,y類自身也包含了指向虛函式的指標。

編譯器在編譯上面這段**的時候將為這shape和circle兩個物件分別建立乙個vtable表,這些表依次填充派生類物件和基類物件中宣告的所有的虛函式位址。如果派生類本身沒有重新定義基類的虛函式,那麼填充的就是基類的虛函式位址。這樣一旦如果函式呼叫乙個派生類不存在的方法時候能夠自動呼叫基類方法。然後編譯器在每個類中放置乙個vptr

,一般置於物件的起始位置,繼而在物件的建構函式中將vptr

初始化為本類的vtable的位址。

c++ 編譯程式時候按下面的步驟進行工作:

(1)為各類建立虛函式表,如果沒有虛函式則不建立。

(2)暫時不連線虛函式,而是將各個虛函式的位址放入虛函式表中。

(3)直接連線各靜態函式。

執行時候,誕生了oneshape

和circleshape

兩個物件,oneshape

物件的vptr

指標指向shape的vtable,circleshape

物件的vptr

指標指向circleshape

的vtable,在執行oneshape.fun

()的時候,fun函式的this指標指向了oneshape

物件,進入fun()之後程式繼續執行this->draw(),由於this指向oneshape

物件,oneshape

的vptr

又指向shape類的vtable,這樣就從vtable中得到需要繫結的函式的位址,並連線起來。同樣,this-> area()也經由oneshape

物件而連線到相應的函式上,如圖。

現在我們執行baseshape.fun()。

函式進入fun函式之後,函式的this指標將指向basefun

物件,另一方面basefun

指向乙個circleshape

,因此this指標指向的實際上為circleshape

物件,而circleshape

的vptr

指標指向circle類的虛函式表,這樣編譯器將從虛擬表中取出circle::draw

()和circle::area

()的位址,進行連線。因為circle本身沒有重新定義area()方法,因此編譯器使用shape的area()方法。如圖:

虛函式 1 靜態聯編與動態聯編,引入虛函式

在實際開發工作中,為提高 的重用性,編寫通用的功能模組,往往需要設計處理幾種不同物件的通用程式,如示例2.1所示。示例清單2.1 include stdio.h include stdlib.h 定義函式指標型別displayinteger,指向返回值為void,引數列表為 const int 的函...

靜態聯編(函式過載)和動態聯編(虛函式)

一 靜態聯編 定義 由於函式過載,編譯器必須檢視函式引數以及函式名就能確定使用哪個函式 這種c c 編譯器可以在編譯過程中完成的聯編,被稱為靜態聯編 函式過載 在同一作用域中,可以有一組具有相同函式名,不同引數列表的函式,這組函式被稱為過載函式 二 動態聯編 定義 使用哪個函式是不能在編譯時確定的,...

虛函式及靜態聯編與動態聯編 學習筆記

c primer plus 第13章 類繼承 由於虛函式與靜動態聯編關係緊密,所以放在一處詳細說明,令請見另一篇文章virtual屬性對類繼承的影響 學習筆記,此文章包含了下面1中第二點的詳細描述及乙個示例。1 提到靜態聯編與動態聯編,我們首先需要來講講virtual函式,虛函式的一些要點 在基類方...