前面兩篇關於多型的部落格已經詳細介紹了多型的基礎知識點和多型的底層實現原理,下面將主要介紹一下單繼承和多繼承的虛函式表~~~
首先來看一段**:
class base
virtual void func2()
private:
int _b = 1;
};class derive :public base
virtual void func3()
virtual void func4()
private:
int _d = 2;
};int main()
再來觀察一下這段**的除錯視窗:
通過除錯視窗可以看出派生類繼承了基類的虛函式,並完成了覆蓋,那麼派生類自己的虛函式去哪了呢 ?這裡是由於編譯器的監視視窗故意隱藏了派生類的兩個虛函式,給我們造成了誤解,那我們又該如何看到派生類的兩個虛函式呢?下面通過一段**來看一下派生類的虛函式:
class base
virtual void func2()
private:
int _b = 1;
};class derive :public base
virtual void func3()
virtual void func4()
private:
int _d = 2;
};//函式指標
typedef void(*vfptr)();
//傳參傳乙個指標陣列(虛表):vfptr vtable==vfptr* vtable
void printvtable(vfptr vtable)
cout << endl;
}int main()
解釋一下這句**:
vfptr* bvtable = (vfptr*)(*(int*)&b);
2、*(int*)&b:再解引用取頭上4個位元組
3、(vfptr*)(*(int*)&b):再強制轉換成vfptr*,因為虛表就是乙個存vfptr型別(虛函式指標型別)的陣列
需要注意的是這段列印虛表的**有可能會崩潰,因為編譯器有時對虛表的處理不乾淨,虛表最後面沒有放nullptr,就會導致越界,這是編譯器的問題,我們只需要清理解決方案就可以了。
輸出結果:
從上述輸出結果中,我們可以看到派生類的虛表中存了自己的虛函式和基類的虛函式。
首先來看一段多繼承的**:
class base1
virtual void func2()
private:
int _b1 = 1;
};class base2
virtual void func2()
private:
int _b2 = 1;
};class derive :public base1,public base2
virtual void func3()
private:
int _d1 = 2;
};//函式指標
typedef void(*vfptr)();
//傳參傳乙個指標陣列代表虛表:vfptr vtable==vfptr* vtable
void printvtable(vfptr vtable)
cout << endl;
}int main()
{ derive d;
vfptr* b1vtable = (vfptr*)(*(int*)&d);
printvtable(b1vtable);
//base2的位置
vfptr* b2vtable = (vfptr*)(*(int*)((char*)&d+sizeof(base1)));
printvtable(b2vtable);
system("pause");
return 0;
輸出結果:
觀察輸出結果可知,多繼承派生類的未重寫的虛函式放在第乙個繼承基類部分的虛函式表中。
單繼承與多繼承中的虛函式表和虛函式指標
編譯環境 vs 2013 首先,我們了解一下何為單繼承,何為多繼承?單繼承 乙個子類只有乙個直接父類。多繼承 乙個子類有兩個或多個直接父類。單繼承中的虛函式表分析 示例程式 include using namespace std typedef void func class base virtua...
單繼承類的虛函式表
列印虛函式表 include include using namespace std class classa int m data1 int m data2 void func1 void func2 virtual void vfunc1 virtual void vfunc2 class cl...
繼承(單繼承 多繼承 菱形繼承 虛繼承)
一 單繼承 單繼承是一種 乙個子類只有乙個直接父類 的繼承關係。二 多繼承 多繼承是一種 乙個子類有兩個或兩個以上直接父類 的繼承關係。三 菱形繼承 菱形繼承由兩個 或以上 單繼承,乙個多繼承構成,結構如下 顯然,上例中assistant類多繼承了student和teacher兩個類,而studen...