详解虚函数的实现过程之菱形继承(5)
大家看到標(biāo)題,會不會菱形繼承的虛表會不會是重復(fù)的呢?祖父類的虛表會不會在子類會不會是兩份相同呢?那么我們一起來探索一下吧,沖沖沖!!
首先我們來分析一下:
它一共定義了四個(gè)類,分別為CFurniture,CSofa,CBed和CSofaBed。CFurniture為祖父類,從CFurniture類中派生了兩個(gè)子類:CSofa與CBed,它們在繼承時(shí)使用了virtual的方式,即虛繼承。
接下來我們來看看CSofaBed的對象的內(nèi)存結(jié)構(gòu)圖
那么這些數(shù)據(jù)都有什么含義呢?如下所示:
看了一下,大概能看懂,但是還有一個(gè)模糊不清的數(shù)據(jù)無法理解,就像CSofaBed_vt(new)和vt_offset,他們又代表什么東西呢?唉,只能去探索匯編代碼,繼續(xù)沖沖沖!!!
在這里解釋一下地址40F732~40F742之間匯編代碼的作用:
ebp-24h是對象的向后偏移四個(gè)字節(jié)的地址,因?yàn)閑bp-28h是this指針,也就是對象的首地址,this值即內(nèi)存圖中的12FF58,所以[ebp-24h]也就是對象的第二個(gè)字節(jié)的數(shù)據(jù),其實(shí)說白了它還是個(gè)地址,也就是12-13內(nèi)存圖中的第二行數(shù)據(jù) 425050,即[ebp-24h]的值是425050,然后放入ecx中,ecx+4也就是這個(gè)地址向后偏移 4個(gè)字節(jié),即425054,然后[ecx+4]的值即為1C,這個(gè)值就是父類虛表指針相對于vt_offset的偏移,然后把這個(gè)值放入edx,作為一個(gè)偏移值,ebp-24h+edx 意思就是相對于第二個(gè)字節(jié)的偏移為1C的地址,[ebp-24h+edx]不就是這個(gè)地址的值了嗎?也就是祖父類的首地址,即祖父類的虛表指針的地址
上面分析了一下匯編代碼,分析出了vt_offset所指向的內(nèi)存地址中保存的數(shù)據(jù)為偏移數(shù)據(jù)。如下圖,圖中每個(gè)vt_offset對應(yīng)的數(shù)據(jù)有兩項(xiàng):第一項(xiàng)是-4,即vt_offset所屬類對應(yīng)的虛表指針相對于vt_offset的偏移值;第二項(xiàng)保存的是父類虛表指針相對于vt_offset的偏移值(上面已分析結(jié)束,至于第一項(xiàng)的話,大家看匯編代碼都能看出)
根據(jù)上面我們找出的vt_offset是地址12FF5C,向下偏移1C的話,1C是多少個(gè)字節(jié)?剛開始我一直搞成12個(gè)字節(jié)?!!!!!我都搞不懂那個(gè)1被我想哪去了?!!!1C也就是 16+12=28個(gè)字節(jié),也就是向下偏移7行,即到地址12FF78處,它的值為42501C,這也就是父類虛指針的地址。當(dāng)然也可以用第二個(gè)來算,因?yàn)樗鼈z的父類都是同一個(gè),所以算出來的地址肯定也是42501C(快速算一下:也就是425044的地址是12FF68,然后向下偏移10h(16個(gè)字節(jié))個(gè)字節(jié),也就是4行,即12FF78處,值為42501C)
根據(jù)前面所述,這里有三個(gè)虛表指針:
0x425034(用0x12FF5C -0x4=0x12FF58,根據(jù)上面內(nèi)存圖此處地址的值為0x425034),0x425028(從匯編代碼地址0x40F752分析得出)(至于0x12FF68如何得來,需要去分析匯編代碼,用0x12FF68 -0x4=0x12FF64,根據(jù)上面內(nèi)存圖此處地址的值為0x425028),
0x42501C(已算出是祖父類起始地址)
所以總結(jié)如下:
vt_offset是一個(gè)地址,這個(gè)地址所指向的地方存在了兩個(gè)偏移值,第一個(gè)值是當(dāng)前類對應(yīng)的虛表指針相對于vt_offset的偏移值,第二個(gè)值是父類對應(yīng)的虛表指針相對于vt_offset的偏移值,每個(gè)虛繼承類都有一個(gè)相應(yīng)的vt_offset,可找到父類的虛表指針,也可找到自身類的虛表指針。
這三個(gè)虛表指針指向的虛表包含了子類CSofaBed含有的虛函數(shù)有了這些記錄就可以隨心所欲地將虛表指針轉(zhuǎn)換成任意的父類指針。
在利用父類指針父類指針訪問虛函數(shù)時(shí),只能調(diào)用子類與父類共有的虛函數(shù),子類繼承自其它父類的虛函數(shù)是無法調(diào)用的,虛表中也沒有相關(guān)記錄。當(dāng)子類的父類存在多個(gè)父類時(shí),會在12-15所顯示的表格中依次記錄它們的偏移。
虛函數(shù)系列:
詳解虛函數(shù)的實(shí)現(xiàn)過程之初探虛表(1)
詳解虛函數(shù)的實(shí)現(xiàn)過程之單繼承(2)
詳解虛函數(shù)的實(shí)現(xiàn)過程之多重繼承(3)
詳解虛函數(shù)的實(shí)現(xiàn)過程之虛基類(4)
詳解虛函數(shù)的實(shí)現(xiàn)過程之菱形繼承(5)
總結(jié)
以上是生活随笔為你收集整理的详解虚函数的实现过程之菱形继承(5)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 详解虚函数的实现过程之虚基类(4)
- 下一篇: 静态反调试技术(1)