C++虛函數(shù)表實例分析
多態(tài)是C++面向?qū)ο蟪绦蛟O計的一個重要特性。以前看到虛函數(shù)覺得很神奇,為什么就能實現(xiàn)多態(tài)了呢。最初的時候曾設想,要實現(xiàn)運行時多態(tài),應該讓對象的某個部分始終指向一個固定的地址,子類繼承的時候,就修改這個地址的內(nèi)容。這樣,父類和子類都是到同一個固定地址去讀取內(nèi)容,在運行時就能表現(xiàn)不同行為。
在看了《深度探索c++對象模型》之后,發(fā)現(xiàn)思路是類似的。在對象中,有一個指針指向一張?zhí)摵瘮?shù)表,里面按照次序存放了每一個虛函數(shù),當子類繼承的時候,即到虛函數(shù)表的指定位置去修改函數(shù)地址。當我們通過父類指針來操作一個子類的時候,調(diào)用虛函數(shù),都是通過虛函數(shù)表+固定的偏移,這樣運行期多態(tài)便實現(xiàn)了。
在深度《深度》這本書中,虛函數(shù)表大多放在了對象的末端,不知道現(xiàn)在的編譯器是什么樣的,因此本文就來實際做個實驗測試一下。
實驗環(huán)境:VC2013 Express
代碼如下:
class Parent { public: int parent; Parent() : parent(10) {} virtual void a() { cout << "Parent::a()" << endl; } virtual void b() { cout << "Parent::b()" << endl; } virtual void c() { cout << "Parent::c()" << endl; } }; class Child : public Parent { public: int child; Child() :child(100) {} virtual void a() { cout << "Child::a()" << endl; } virtual void b_child() { cout << "Child::b_child()" << endl; } virtual void c_child() { cout << "Child::c_child()" << endl; } }; class GrandChild : public Child{ public: int grandchild; GrandChild() :grandchild(1000) {} virtual void a() { cout << "GrandChild::a()" << endl; } virtual void b_child() { cout << "GrandChild::b_child()" << endl; } virtual void c_grandchild() { cout << "GrandChild::c_grandchild()" << endl; } }; int main() { typedef void(*func)(); GrandChild grandchild; int **vtable = (int **)&grandchild; for (int i = 0; (func)vtable[0][i] != nullptr; i++) { auto pfunc = (func)vtable[0][i]; cout << " ["<<i<<"] "; pfunc(); } return 0; }
結果顯示如下圖所示:
確實,虛函數(shù)表指針在對象起始處,并看到了對應項被覆蓋。
相關文章
WM_CLOSE、WM_DESTROY、WM_QUIT及各種消息投遞函數(shù)詳解
這篇文章主要介紹了WM_CLOSE、WM_DESTROY、WM_QUIT及各種消息投遞函數(shù),有助于讀者更好的理解windows程序的消息機制,需要的朋友可以參考下2014-07-07