C 多型原理

2021-06-05 22:19:16 字數 1723 閱讀 1150

靜態多型性比較簡單,主要動態多型性比較難理解。

動態多型性有兩個條件:

1、在基類中必須使用虛函式、純虛函式

2、呼叫函式時要使用基類的指標或引用。

只要在基類的成員函式前加上virtual,該成員函式就是虛函式,從基類派生出來的類的同名成員函式,不管前面是否有virtual,同樣是虛函式,在虛函式的實現時,前面不能加virtual。

內聯函式不能是虛函式,因為內聯函式不能在執行時動態確定位置,即使虛函式在類的內部定義,但在編譯的時候仍然看做是非內聯的。

只有類的成員函式才能宣告為虛函式,普通函式不能宣告為虛函式。

靜態成員函式不能是虛函式。

虛函式的原理:

普通函式的處理:

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

虛函式的處理:

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

虛函式表的結構:

它是乙個函式指標表,每乙個表項都指向乙個函式。任何乙個包含虛函式的類都會有這樣一張表。需要注意的是vtable只包含虛函式的指標,沒有函式體。實現上是乙個函式指標的陣列。

虛函式表既有繼承性又有多型性

每個派生類的vtable繼承了它各個基類的vtable,如果基類vtable中包含某一項,則其派生類的vtable中也將包含同樣的一項,但是兩項的值可能不同。如果派生類過載(override)了該項對應的虛函式,則派生類vtable的該項指向過載後的虛函式,沒有過載的話,則沿用基類的值。

每乙個類只有唯一的乙個vtable,不是每個物件都有乙個vtable,每個物件都有乙個指標,這個指標指向該類的vtable(當然,前提是這個類包含虛函式)。

那麼,每個物件只額外增加了乙個指標的大小,一般說來是4位元組。

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

在通過物件指標呼叫乙個虛函式時,編譯器生成的**將先獲取物件類的vtable指標,然後呼叫vtable中對應的項。

對於通過物件指標呼叫的情況,在編譯期間無法確定指標指向的是基類物件還是派生類物件,或者是哪個派生類的物件

但是在執行期間執行到呼叫語句時,這一點已經確定,編譯後的呼叫**能夠根據具體物件獲取正確的vtable,呼叫正確的虛函式,從而實現多型性。

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

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

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

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

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

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

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

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

c 多型原理

1 當類中宣告虛函式時,編譯器會在類中生成乙個虛函式表 2 虛函式表是乙個儲存類成員函式指標的資料結構 3 虛函式表是由編譯器自動生成與維護的 4 virtual成員函式會被編譯器放入虛函式表中 5 當存在虛函式時,每個物件中都有乙個指向虛函式表的指標 c 編譯器給父類物件 子類物件提前布局vptr...

C 多型實現原理

用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。存在虛函式的類都有乙個一維的虛函式表叫做虛表。類的物件有乙個指向虛表開始的虛指標。虛表是和類對應的,虛表指標是和物件對應的。多型性是乙個介面多種實現,是物件導向的核心。分為類的多型性和函式的多型性。多型用虛函式來實現,結合動態繫結...

C 多型的原理

這裡常考一道筆試題 sizeof base 是多少?這裡 sizeof base 8。int型別4個位元組 virtual中含乙個指標 4個位元組 8個位元組 無論有幾個虛函式,只有乙個指標,指標指向虛函式表 class base private int b 1 通過觀察測試我們發現b物件是8byt...