今天看到一道c++筆試題,描述如下:
#include "stdio.h"
class a
};class b: public a
virtual void test()
};class c: public b
};void main()
輸出是什麼?
正確的答案是:
c test
b test
為什麼呢,明明func函式並不是虛函式((b *)(&c))->func();為什麼虛函式機制會起作用呢?
我認為這個要從c++虛函式實現的原理來討論。在《深度探索c++物件模型》裡描述了現在c++虛函式機制實現原理是通過虛函式表來實現的。
也就是說物件c在記憶體中的儲存是這樣的
int loc
-指向虛函式表的指標 _vptr
((b *)(&c))->func();這裡可以理解成 b * ptmp = &c; ptmp -> func();
當基類指標指向子類物件,會將子類物件的引用隱式轉換成基型別的指標,但是它的本質還是乙個子型別的引用。當ptmp呼叫func()時,由於func()不是虛函式,所以虛函式機制不起作用,c++根據當前的型別去尋找對應的函式,所以會去呼叫b類的func()函式,而b類的func()函式呼叫了test()函式,這個函式是乙個虛函式,那麼c++就會根據_vptr去尋找對應的虛函式來執行,由於c++是根據記憶體偏移量來尋找_vptr的,所以此時的_vptr指向的位址表示的是c類的test函式位址,所以會輸出c test;
((b)c).func();當執行這句時,由於把c轉換成了基型別的物件,那麼他的本質就變成了基類的物件,當執行到test()時,c++依舊根據偏移量來尋找_vptr,此時找到的_vptr則是父類的_vptr,所以會輸出:b test;
個人感覺這裡面的坑還是挺大的,只要記住:虛函式機制只有基類通過引用或指標指向派生類時,虛函式機制才會發生;當派生類轉換成基類時,派生類的本質就發生了改變,表示乙個基類物件,虛函式機制不會發生,c++通過檢視變數的型別來決定執行基類的方法。基類的引用也好指標也好,他們在記憶體中都只是占用8位元組空間(64位)而已,宣告為基類的引用或指標表示的是指向的記憶體空間的讀取方式應該按照基類的讀取方式來讀取,但是這個子類的物件本身占用的記憶體空間是不變的,擁有的虛函式表的指標的偏移量也是固定的,所以虛函式機制可以發生。 c 虛函式機制
rt。面試常問的題 首先c 的虛函式機制是用來實現物件導向程式設計時的多型機制的。多型 polymorphism 是允許你將父物件設定成為與乙個或更多的他的子物件相等的技術。簡單的說 就是允許將子類型別的指標賦值給父類型別的指標。這樣在定義乙個基類的指標物件p1後,可以通過p1來呼叫各個子類的函式以...
C 虛函式實現機制
看完之後,對c 中的虛函式實現機制算的上是恍然大悟,但是個人感覺博文中有幾點不足之處,現在一一枚舉,以下語言僅僅代表個人看法 1.定位虛表的方式 大家都知道含有虛函式的類的例項裡面前4個位元組是虛函式指標占用的記憶體,裡面填充的是虛函式表的位址號。原博文中通過乙個long型別的物件取得前四個位元組的...
c 虛函式實現機制
1 c 實現多型的方法 其實很多人都知道,虛函式在c 中的實現機制就是用虛表和虛指標,但是具體是怎樣的呢?從more effecive c 其中一篇文章裡面可以知道 是每個類用了乙個虛表,每個類的物件用了乙個虛指標。具體的用法如下 class a class b public a a,b的實現省略 ...