虛函數(shù)與對(duì)象布局
類布局
代碼 | 類布局 |
class Base1 { public: void f0() {} virtual void f1() {} virtual void f2() {} virtual void f3() {} int int_in_b1; }; class Middle2 : public Base1 { public: virtual void g1() {} virtual void g2() {} virtual void g3() {} int int_in_b2; }; class Top3 : public Middle2 { public: virtual void h1() {} virtual void h2() {} virtual void h3() {} int int_in_b3; virtual void f1() {} }; |
----------------------------------- class Base1 size(8): +--- 0 | {vfptr} 4 | int_in_b1 +--- Base1::$vftable@: | &Base1_meta | 0 0 | &Base1::f1 1 | &Base1::f2 2 | &Base1::f3 ----------------------------------- class Middle2 size(12): +--- | +--- (base class Base1) 0 | | {vfptr} 4 | | int_in_b1 | +--- 8 | int_in_b2 +--- Middle2::$vftable@: | &Middle2_meta | 0 0 | &Base1::f1 1 | &Base1::f2 2 | &Base1::f3 3 | &Middle2::g1 4 | &Middle2::g2 5 | &Middle2::g3 ----------------------------------- class Top3 size(16): +--- | +--- (base class Middle2) | | +--- (base class Base1) 0 | | | {vfptr} 4 | | | int_in_b1 | | +--- 8 | | int_in_b2 | +--- 12 | int_in_b3 +--- Top3::$vftable@: | &Top3_meta | 0 0 | &Top3::f1 1 | &Base1::f2 2 | &Base1::f3 3 | &Middle2::g1 4 | &Middle2::g2 5 | &Middle2::g3 6 | &Top3::h1 7 | &Top3::h2 8 | &Top3::h3 -----------------------------------> |
輸出虛表
Visual C++在cl編譯時(shí)加上命令行"/d1 reportAllClassLayout"或"/d1 reportSingleClassLayoutXXX",XXX換成類名,會(huì)輸出類的對(duì)象布局。命令行: cl c:\foo.cpp /c /d1 reportAllClassLayout
IDE:在設(shè)置里C++命令里加上這行命令。
參考
How can one inspect a vtable in Visual C++?Diagnosing Hidden ODR Violations in Visual C++ (and fixing LNK2022)
結(jié)論
- 對(duì)象的開始4個(gè)字節(jié)始終是虛表的地址(如果有)。這個(gè)結(jié)論在查對(duì)象被破壞、運(yùn)行時(shí)崩潰等bug時(shí)很重要。
- 類只有一個(gè)虛表。基類的虛函數(shù)和自身的都會(huì)合并到一個(gè)地址里去。
- 如果繼承類重載了某個(gè)虛函數(shù),其實(shí)在虛表里是會(huì)將基類被重載的虛函數(shù)從虛表里‘抹掉’,所以你要訪問基類里被重載了的虛函數(shù),只能用“基類::函數(shù)名”訪問。例如上面的‘Top3::f1 ’。
- 虛函數(shù)不會(huì)增加對(duì)象體積吧,以前怎么會(huì)有這個(gè)觀念...
posted on 2014-07-04 16:09 的筆記 閱讀(403) 評(píng)論(0) 編輯 收藏 引用 所屬分類: C++