C 多型的實現及原理

2021-09-09 06:30:06 字數 2560 閱讀 8186

c++的多型性用一句話概括就是:在基類的函式前加上virtual關鍵字,在派生類中重寫該函式,執行時就會根據物件的實際型別來呼叫相應的函式,如果物件型別是派生類,就呼叫派生類中的函式,如果物件型別是基類,就呼叫基類函式。

1.用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。

2.存在虛函式的類都有乙個一維的虛函式的虛表,類的物件都有乙個指向虛表頭的指標。虛表是類的,虛表指標是物件的。

3.多型性是乙個介面多種實現,是物件導向的核心,分為類的多型性和函式的多型性。

4.多型用虛函式來實現,結合動態繫結。

5.純虛函式是虛函式再加上=0。

6.抽象類是☞包括至少乙個虛函式的類。

備註:純虛函式:virtual void func() = 0;即抽象類,即先有名稱,沒有內容,在派生類中實現內容。

#include

using

namespace std;

class

base

void

say()}

;class

derived

:public base};

void

test()

結果為:

我們在test()函式中定義了乙個derived類的物件d,接著定義了乙個base類的指標變數pb,然後利用該變數呼叫say()函式,認為d實際上是derived的物件,應該呼叫derived類的say(),但是結果不是。

class

base

void

virtual

say()}

;class

derived

:public base};

void

test()

執行結果如下:

我們發現結果是"derived::say",也就是根據物件的型別呼叫了正確的函式,那麼當我們將say()函式宣告為virtual時,背後發生了什麼。

編譯器在變異的時候,發現base類中有虛函式,此時編譯器會為每個包含虛函式的類建立乙個虛表(vtable),該表是乙個一維陣列,在這個陣列中存放每個虛函式的位址。

如何定位虛表,編譯器另外還為每個物件提供了乙個虛表指標(vptr),這個指標指向了物件所屬類的虛表,在程式執行時,根據物件的型別去初始化vptr,從而讓vptr指向正確的類的虛表,從而在呼叫虛函式的時候,能夠正確找到虛函式,對於第二段程式,由於pb實際指向的物件的型別是derived,因此vptr指向derived類的vtable,當呼叫pb->say()時,根據虛表的函式位址找到的就是derived的say()函式。

問題:

由於每個物件呼叫的虛函式都是用過虛表指標來索引的,也就決定了虛表指標的正確的初始化時非常重要的,換句話說,如果虛表指標沒有初始化,我們就不能呼叫虛函式,那麼虛表指標在什麼時候,什麼地方初始化?

答案:

在建構函式中進行虛表指標的建立及其初始化,在構造子類物件時,要先呼叫基類的建構函式,此時編譯器只看到了基類,並不知道後面還有繼承者,它初始化基類的虛表指標,該虛表指標指向基類的虛表,當執行子類的建構函式時,子類物件的虛表指標被初始化,指向自身的虛表。

簡單總結(基類有虛函式):

1.每個類都有虛表

2.如果子類沒有重寫虛函式,那麼子類虛表仍然會有該函式的位址,只不過這個位址指向的是基類的虛函式實現,如果基類有3個虛函式,那麼基類的虛表中就有3項(虛函式的位址),派生類也會有虛表,至少有3項,如果重寫了相應的虛函式,那麼虛表中的位址就會改變,指向自身的虛函式實現,如果派生類有自己的虛函式,那麼虛表中就會新增該項。

3.派生類的虛表中虛函式位址的排列順序和基類的虛表中虛函式位址排列順序相同:

這就是c++的多型性,當c++編譯器在編譯的時候,發現某個類的某個函式是虛函式,這個時候c++就會採用晚繫結技術,也就是在編譯時並不確定具體呼叫的函式,而是在執行時,依據物件的型別確認呼叫哪乙個函式,這就叫做c++的多型性,我們沒有在函式前加virtual時,c++編譯器就確定了那個函式被呼叫,這就叫做早繫結

c++的多型性就是通過晚繫結技術實現的。

基類虛表構建過程:

(i)按照虛函式的宣告次序新增到虛表中

派生類虛表構建過程:

(i)將基類虛表中的內容拷貝乙份放到派生類的虛表中

(ii)如果派生類重寫了基類中的虛函式,用派生類自己虛函式替換虛表中相同偏移量位置的基類虛函式

(iii)派生類對於自己新增加的虛函式將其按照在派生類中的宣告次序放在派生類虛表的最後

C 多型實現及原理

include include using namespace std class person men women 執行結果 men 1peter women 2lily delete men delete person delete women delete person 繼承機制中,子類訪問父...

C 多型的實現及原理

c 的多型性用一句話概括就是 在基類的函式前加上virtual關鍵字,在派生類中重寫該函式,執行時將會根據物件的實際型別來呼叫相應的函式。如果物件型別是派生類,就呼叫派生類的函式 如果物件型別是基類,就呼叫基類的函式 1 用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。2 存在...

C 多型的實現及原理

c 的多型性用一句話概括就是 在基類的函式前加上virtual關鍵字,在派生類中重寫該函式,執行時將會根據物件的實際型別來呼叫相應的函式。如果物件型別是派生類,就呼叫派生類的函式 如果物件型別是基類,就呼叫基類的函式 1 用virtual關鍵字申明的函式叫做虛函式,虛函式肯定是類的成員函式。2 存在...