這篇文章所使用的方法來(lái)源于 CuteQt博客 上的一篇文章:http://www.cuteqt.com/blog/?p=868
生成對(duì)象內(nèi)存布局所使用的方法來(lái)自于vc8編譯器一個(gè)未公開(kāi)的參數(shù),即 /d1 reportSingleClassLayoutXXX或者 /d1 reportAllClassLayout,MSDN上關(guān)于這個(gè)的簡(jiǎn)單說(shuō)明及示例可以見(jiàn)這里:http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx
一般來(lái)說(shuō)用reportSingleClassLayout,因?yàn)閞eportAllClassLayout會(huì)生成許多中間類的結(jié)果,干擾我們的分析。
按照上面博客中介紹的方法,一步步來(lái)跟蹤各種虛函數(shù)使用情況下的對(duì)象內(nèi)存布局,可以很直觀的看到虛函數(shù)是怎樣分布的,各種繼承情況下虛函數(shù)是又是怎樣生成的,等等。
一點(diǎn)簡(jiǎn)單的總結(jié):
1。以前常說(shuō)的,因?yàn)樘摵瘮?shù)的使用,使得類多了一個(gè)vtable指針,大小增加了4字節(jié),其實(shí)是不完全正確的。因?yàn)橐粋€(gè)class內(nèi)可能會(huì)有多個(gè)虛表的存在,比如當(dāng)有多個(gè)帶虛函數(shù)的父類時(shí)。
2。多個(gè)虛函數(shù)在虛表里的順序由其定義順序決定。如果是從多個(gè)父類派生來(lái)的,則這多個(gè)虛表的順序由父類的申明順序而定。
3。多繼承情況下的同名虛函數(shù)處理使用了一種叫做thunk的技術(shù),這樣通過(guò)不同的基類調(diào)用同名的虛函數(shù)時(shí),都會(huì)調(diào)用到相同的函數(shù)體內(nèi)。
4。虛基類的實(shí)現(xiàn)多了一個(gè)vbi表,記錄的是虛基類中的虛函數(shù)表地址信息。同時(shí)在派生類中計(jì)算好了到這個(gè)vbi表的偏移,這樣虛基類里的虛函數(shù)在菱形繼承關(guān)系的派生類中就只有了一份實(shí)現(xiàn)。
5。使用的時(shí)候其實(shí)不必要意這些細(xì)節(jié)問(wèn)題,編譯器在生成函數(shù)調(diào)用代碼時(shí)已經(jīng)幫我們處理好了,即這個(gè)函數(shù)在哪個(gè)虛表中,是第幾個(gè)虛函數(shù),最終也就是要做多少個(gè)字節(jié)的偏移。