c 實函式虛函式在繼承體系中是如何呼叫的

2021-06-18 03:52:36 字數 1316 閱讀 4223

函式是屬於類的,不是屬於物件。

我們來講函式的呼叫機制,

在c++中函式分為,實函式和虛函式,他們的呼叫機制不同。

先來看看類的編譯資訊,

對於乙個類他的編譯資訊中含有 1.實函式,2.虛函式,這些靜態呼叫是用,

由於虛函式有動態呼叫的特徵,所以虛函式存在乙個虛函式表裡,被所有的物件共享。

既然虛函式資訊既在類資訊中,也在虛函式表中,那麼虛函式呼叫是如何區分的了?

1.靜態呼叫,當虛函式書靜態呼叫是,直接用編譯類的資訊中的虛函式資訊

2.動態呼叫,當虛函式是動態呼叫是,需要呼叫虛函式表中的函式資訊,這也是c++多型的基本機制。

對於虛函式表中的函式,在單繼承體制中,子類的虛函式會把基類的虛函式表拷貝過來,同時子類中的虛函式會覆蓋拷貝過來基類同函式簽名的虛函式。

但是並不是表示你在子物件中無法使用基類中被覆蓋的函式,因為類編譯資訊中儲存了基類函式所有資訊,只要應用類編譯資訊,就可以呼叫基類中的所有函式,靜態呼叫。

下面我們來驗證,列印虛函式表中的所有函式資訊;

如何列印虛函式表中的資訊,

在物件中,最開始的四個位元組(win 32)是vfptr,指向虛函式表的指標,通過它可以訪問虛函式

b b;

int ** vftalbe=(int **)(&b);

vftable[0][0],就是第乙個函式的位址,

vftable[0][1],就是第二個函式位址;

結果解釋

繼承類 drived 

拷貝了繼承的虛函式

base::ff()

base:: gg();

由於繼承類含有同函式簽名的函式 drived:: gg();

所有在虛函式表中,繼承類的函式會覆蓋掉基類的函式 base::gg();

所以輸出 ddived;;gg,而不是base :: gg();

覆蓋了只是在虛函式表中覆蓋 ,但是不會在變數類資訊中覆蓋,

所以仍然可以通過靜態呼叫來使用函式 base::gg();

drived d;

d.base::g();

虛函式 虛繼承 C

關於虛表,我們就要用到乙個關鍵字 virtual,可以修飾函式,也可以修飾類。類的成員函式被virtual修飾之後,就成為了虛函式 修飾類,主要是虛繼承。在此之前,我們首先要了解乙個概念 物件模型,也就是說,乙個基類形成之後,裡面的成員是怎麼存放的,當派生類繼承基類之後,派生類的成員是怎麼存放的。我...

C 繼承 虛函式

part 1.虛函式 關於c 繼承,我們先來看一小段 base表示基類,derived表示base的繼承類。include using namespace std class base base void print protected protected許可權,繼承類可訪問 int base a,...

c 中虛函式繼承,虛表剖析

虛表概念 對於有虛函式類,編譯器都會維護一張虛表,物件的前四個位元組就是指向虛表的指標。虛表中存放的是虛函式的位址。虛函式按照其宣告順序存放在虛表中。在派生類中,前面是繼承基類的虛函式,若派生類重寫了基類中的虛函式則替換為重寫後的,派生類自己的虛函式追加在其後。如果派生類繼承了兩個基類,則派生類自己...