C++ 虛表虛函數怎麼就實現了多態?

虛表vftable,編譯器爲每一個擁有虛函數的類都建有一張虛函數表,裏面存有虛函數的入口指針(地址)。在類對象的內存佈局中,先是一個vfptr虛表指針,指向虛表首地址,然後經過偏移量的形式來訪問虛表中的地址。html

看許多文章都在那裏侃侃而談,然能實際展現類(對象)內存佈局者寥寥,不可見內裏實現的終究是借他人文字的空想。now, 咱們來一窺究竟!ios


 

PS:如何利用VS查看類內存佈局見文末連接ide

1. 帶虛函數類內存佈局函數

2. 發生單繼承時,派生類內存佈局,先是複製一份基類內存佈局,而後是本身的佈局(注意內存對齊)。虛表指針指向本身的虛表,派生類虛函數地址若是本身未覆蓋,那麼就是基類的,不然是本身的函數地址。佈局

3. 發生多繼承時:先按照繼承順序,從左到右排布基類的佈局包括虛標指針,而後排布本身的指針和數據;派生類虛表排布形式是按照繼承順序,是繼承來的虛函數,若是有覆蓋則換成本身的函數地址;而後是下一個基類,直至基類排布完畢。繼承來的多張表是獨立的(從內存佈局中的多個虛表指針能夠看出),且使用首地址+偏移量的形式來訪問。測試

4. 發生虛繼承時:不管是對象內存排布仍是虛表,虛基類的部分都被放到最後排布,且若是派生類有本身的虛函數則會加在第一個基類的虛表末尾。spa

除vfptr和vftable以外,增長了vbtable 虛基類表(存放繼承的虛基類的地址)和 vbptr(指向虛基類表的指針)命令行

 

測試代碼debug

 1 #include <iostream>
 2 class Base  3 {  4     int a;  5     int b;  6 public:  7     virtual void foo() {};  8     virtual void bar() {};  9     virtual void bar2(){}; 10     virtual void bar3(){}; 11 }; 12 
13 class Base2 14 { 15     int d; 16 public: 17     virtual void foo() {}; 18 }; 19 
20 class Derived : virtual public Base, public Base2 21 { 22     int c; 23 public: 24     //void foo() {};
25     void bar() override {}; 26     virtual void bar4() {}; 27 }; 28 
29 int main() 30 { 31  Base b; 32  Derived d; 33     return 0; 34 }
測試代碼

多態原理?我的理解3d

1. C++多態動態創建在虛函數上,使用virtual關鍵字指明不要在編譯器綁定函數地址,而是在運行時訪問虛函數表,即動態綁定。

2. 使用基類指針指向派生類對象且調用虛函數時(前提是派生類覆蓋了基類虛函數),運行時該指針指向的地址是派生類對象地址,在派生類對象地址頭就是指向虛函數表的vfptr,這張虛表天然是派生類的,而在構造虛表的過程當中該虛函數早就被派生類本身的函數地址所覆蓋,因此調用函數天然是派生類的函數。

3. 多態的含義:基類指針能夠指向基類對象以及不一樣派生類對象,實現了一種寫法,多種訪問方式的效果,稱爲多態。


 【參考資料】

如何利用VS查看類內存排布:http://www.javashuo.com/article/p-uovgyogi-dm.html

(在VS項目右鍵屬性->C/C++->命令行->添加 /d1 reportAllClassLayout  應用便可,注意debug/release還有平臺類型)

C++多態以及虛函數的不錯文章:http://www.javashuo.com/article/p-gobzqpwp-ms.html

相關文章
相關標籤/搜索