C++虛函數(shù)表實(shí)例分析
多態(tài)是C++面向?qū)ο蟪绦蛟O(shè)計(jì)的一個(gè)重要特性。以前看到虛函數(shù)覺得很神奇,為什么就能實(shí)現(xiàn)多態(tài)了呢。最初的時(shí)候曾設(shè)想,要實(shí)現(xiàn)運(yùn)行時(shí)多態(tài),應(yīng)該讓對象的某個(gè)部分始終指向一個(gè)固定的地址,子類繼承的時(shí)候,就修改這個(gè)地址的內(nèi)容。這樣,父類和子類都是到同一個(gè)固定地址去讀取內(nèi)容,在運(yùn)行時(shí)就能表現(xiàn)不同行為。
在看了《深度探索c++對象模型》之后,發(fā)現(xiàn)思路是類似的。在對象中,有一個(gè)指針指向一張?zhí)摵瘮?shù)表,里面按照次序存放了每一個(gè)虛函數(shù),當(dāng)子類繼承的時(shí)候,即到虛函數(shù)表的指定位置去修改函數(shù)地址。當(dāng)我們通過父類指針來操作一個(gè)子類的時(shí)候,調(diào)用虛函數(shù),都是通過虛函數(shù)表+固定的偏移,這樣運(yùn)行期多態(tài)便實(shí)現(xiàn)了。
在深度《深度》這本書中,虛函數(shù)表大多放在了對象的末端,不知道現(xiàn)在的編譯器是什么樣的,因此本文就來實(shí)際做個(gè)實(shí)驗(yàn)測試一下。
實(shí)驗(yà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;
}
結(jié)果顯示如下圖所示:

確實(shí),虛函數(shù)表指針在對象起始處,并看到了對應(yīng)項(xiàng)被覆蓋。
相關(guān)文章
C++普通函數(shù)指針與成員函數(shù)指針實(shí)例解析
這篇文章主要介紹了C++普通函數(shù)指針與成員函數(shù)指針,很重要的知識點(diǎn),需要的朋友可以參考下2014-08-08
C/C++ 中sizeof(''a'')對比詳細(xì)介紹
這篇文章主要介紹了C/C++ 中sizeof('a')的值對比詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-02-02
C++類中的常數(shù)據(jù)成員與靜態(tài)數(shù)據(jù)成員之間的區(qū)別
常數(shù)據(jù)成員是指在類中定義的不能修改其值的一些數(shù)據(jù)成員,類似于我們以前學(xué)過的常變量,雖然是變量,也有自己的地址,但是一經(jīng)賦初值,便不能再被修改2013-10-10
詳解如何將Spire.PDF for C++集成到C++程序中
Spire.PDF for C++ 是一個(gè)專業(yè)的 PDF 庫,供開發(fā)人員在任何類型的 C++ 應(yīng)用程序中閱讀、創(chuàng)建、編輯和轉(zhuǎn)換 PDF 文檔,本文主要介紹了兩種不同的方式將 Spire.PDF for C++ 集成到您的 C++ 應(yīng)用程序中,希望對大家有所幫助2023-11-11
C語言判斷數(shù)是否為素?cái)?shù)與素?cái)?shù)輸出
大家好,本篇文章主要講的是C語言判斷數(shù)是否為素?cái)?shù)與素?cái)?shù)輸出,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
詳解C++值多態(tài)中的傳統(tǒng)多態(tài)與類型擦除
值多態(tài)是一種介于傳統(tǒng)多態(tài)與類型擦除之間的多態(tài)實(shí)現(xiàn)方式,借鑒了值語義,保留了繼承,在單繼承的適用范圍內(nèi),程序和程序員都能從中受益。這篇文章主要介紹了C++值多態(tài)中的傳統(tǒng)多態(tài)與類型擦除,需要的朋友可以參考下2020-04-04

