沿途總是會出現關於c++虛函式表的問題,今天做一總結:
1.什麼是虛函式表:
虛函式(
virtual function
)是通過一張虛函式表(
virtual table
)來實現的。簡稱為
v-table
。在這個表中,主是要乙個類的虛函式的位址表,這張表解決了
繼承、覆
蓋的問題,\
保證其容真實反應實際的函式。這樣,在有虛函式的類的例項中這個表被分配在了這個例項的記憶體中,所以,當我們用父類的指標來
操作乙個子類的時
候,這張虛函式表就顯得
由為重要了,它就像乙個地圖一樣,指明了實際所應該呼叫的函式。
看乙個例子:
#pragma once
//c++中的虛函式的作用主要是實現了多型的機制
//通過base的例項來得到虛函式表
class base
virtual void g()
virtual void h()
};typedef void(*fun)(void);
void test()
}
結果截圖:
關於**中函式指標,已加說明。通過對物件位址的強轉輸出得到虛函式表的位址,即所謂的虛表指標內容:
由於是兩次進函式,故位址有變,但是道理沒錯!虛表指標就是 _vfptr;
2.無虛函式覆蓋的一般繼承:(虛表)
看**:
#pragma once
//一般繼承(無虛函式覆蓋)
class base
virtual void g()
virtual void h()
};//無覆蓋 公有繼承
class derive :public base
virtual void g1()
virtual void h1()
};void test()
請看,在此繼承中,子類沒有過載任何父類函式,則子類的函式表在vs2013下是這樣的:
發現沒,d是乙個子類物件,子類繼承父類,虛函式表中盡然只有父類的虛函式位址,子類自己的虛函式都沒有顯示,這是不可能的啊
很顯然,這可能就是編譯器的bug,但其實,真實的子類虛函式表是這樣的:
可以看出:
1》虛函式按照宣告順序存放於虛表中;
2》子類虛函式在基類虛函式之後;
3.有虛函式覆蓋的一般繼承:(虛表)
看**:
#pragma once
//有虛函式覆蓋的一般繼承
//有覆蓋是必然的,否則,虛函式將失去作用
class base
virtual void g()
virtual void h()
};//乙個覆蓋 公有繼承
class derive :public base
//注意:這裡函式覆蓋了基類的相同函式;
virtual void g1()
virtual void h1()
};void test()
執行結果:
很明顯基類物件呼叫基類的函式,子類物件,「
好像」也呼叫子類函式,好像的原因看下面:
分析:1》覆蓋的虛函式f()存放在虛表中原來父類虛函式的位置。
2》其他函式依舊
3》這裡還是同樣沒有顯示子類虛函式存放在表中,個人堅持認為,是編譯器的bug,真實展示如下:
可見:覆蓋的虛函式f()存放在虛表中原來父類虛函式的位置,這也是基類物件*p訪問 f() 時,訪問的直接是子類的虛函式,完美的體現了多型;
有關多型,請在見另一篇部落格:
另外有關多重繼承,見下篇;
賜教!
詳談C 虛函式表那回事(多重繼承關係)
1.無虛函式覆蓋的多重繼承 pragma once 無覆蓋,多重繼承 class base1 virtual void g virtual void h class base2 virtual void g virtual void h class base3 virtual void g virt...
詳談C 虛函式表那回事(多重繼承關係)
1.無虛函式覆蓋的多重繼承 pragma once 無覆蓋,多重繼承 class base1 virtual void g virtual void h class base2 virtual void g virtual void h class base3 virtual void g virt...
C 虛函式表研究 (一) 單繼承
c 虛函式表研究 一 單繼承 本文研究單繼承情況下,c 物件的虛函式表的具體情況。所用的編譯器為vc6.0。假設有兩個類a,b,其中b由a派生出來,a含有虛函式fun1,b含有虛函式fun2 a 的定義如下 b的定義如下 測試的 如下 測試 說明 虛函式表指標 int b 虛函式表位址 int b ...