函式是屬於類的,不是屬於物件。
我們來講函式的呼叫機制,
在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 中虛函式繼承,虛表剖析
虛表概念 對於有虛函式類,編譯器都會維護一張虛表,物件的前四個位元組就是指向虛表的指標。虛表中存放的是虛函式的位址。虛函式按照其宣告順序存放在虛表中。在派生類中,前面是繼承基類的虛函式,若派生類重寫了基類中的虛函式則替換為重寫後的,派生類自己的虛函式追加在其後。如果派生類繼承了兩個基類,則派生類自己...