我看vc6中虛繼承的實現

來源:互聯網
上載者:User
我看vc6中虛繼承的實現

這兩天試了一下,來說兩句

因手頭上只有vc6編譯器,故只看了vc6的方式

我的測試程式如下
#include "stdafx.h"
class mostbase1
{
public:
 mostbase1():i(1){};
 int i;
};
class mostbase2
{
public:
 mostbase2():j(2){};
 int j;
};

class base1:public virtual mostbase1,public virtual mostbase2
{
};
class base2:public virtual mostbase1,public virtual mostbase2
{
};
class derived:public base1,public base2
{
};
void f(derived* pderived)
{
 mostbase1* pbase1 = pderived;
 mostbase2* pbase2 = pderived;
 int k = pderived->i;
 k = pderived->j;
 k = pbase1->i;
 k = pbase2->j;
}
int main(int argc, char* argv[])
{
 derived d;
 f(&d);
 printf("Hello World! ");
 return 0;
}
經過我的測試及查看彙編代碼,得知vc的虛基類轉換確如Inside the c++ objects model中所說是用一個virtual base class table來實現的
base1和base2中各有一個__vbct__ptr(大小是4個位元組)用來指向一個virtual base class table,該Table Store著base類中虛基類在base類中的位移,其後就是資料,當derived繼承自base1和base2,首先是存放base1和base2的__vbct_ptr,再就是資料,將base1和base2相同基類的資料放到一起
base1類的記憶體布局如下(base2與base1相同):
pvoid* __vbct_base1  ----先是虛基類表的地址,此時__vbct_base1資料如下
      ----00 00 00 00 04 00 00 00 08 00 00 00
      ----mostbase1在base1中的位移為[__vbct_base1+4]的值
int i;     ----mostbase1類中的i
int j;     ----mostbase2類中的j

derived類的記憶體布局如下:
pvoid* __vbct_base1; ----base1類的虛基類表的地址,其中的值有變化,資料如下
                                ----00 00 00 00 08 00 00 00 0C 00 00 00
pvoid* __vbct_base2; ----base2類的虛基類表的地址,資料如下
                                ----00 00 00 00 04 00 00 00 08 00 00 00
int i;
int j;

 

下面是f(derived* pderived)函數的彙編代碼,對其它進行分析

29:   void f(derived* pderived)
30:   {
0040C230   push        ebp
0040C231   mov         ebp,esp
0040C233   sub         esp,60h
0040C236   push        ebx
0040C237   push        esi
0040C238   push        edi
0040C239   lea         edi,[ebp-60h]
0040C23C   mov         ecx,18h
0040C241   mov         eax,0CCCCCCCCh
0040C246   rep stos    dword ptr [edi]
31:       mostbase1* pbase1 = pderived;
0040C248   cmp         dword ptr [ebp+8],0          [1]
0040C24C   jne         f+27h (0040c257)
0040C24E   mov         dword ptr [ebp-18h],0        [2]
0040C255   jmp         f+35h (0040c265)
0040C257   mov         eax,dword ptr [ebp+8]
0040C25A   mov         ecx,dword ptr [eax]          [3]
0040C25C   mov         edx,dword ptr [ebp+8]
0040C25F   add         edx,dword ptr [ecx+4]        [4]
0040C262   mov         dword ptr [ebp-18h],edx
0040C265   mov         eax,dword ptr [ebp-18h]
0040C268   mov         dword ptr [ebp-4],eax        [5]
32:       mostbase2* pbase2 = pderived;
0040C26B   cmp         dword ptr [ebp+8],0
0040C26F   jne         f+4Ah (0040c27a)
0040C271   mov         dword ptr [ebp-1Ch],0        [6]
0040C278   jmp         f+58h (0040c288)
0040C27A   mov         ecx,dword ptr [ebp+8]
0040C27D   mov         edx,dword ptr [ecx]          [7]
0040C27F   mov         eax,dword ptr [ebp+8]  
0040C282   add         eax,dword ptr [edx+8]        [8]
0040C285   mov         dword ptr [ebp-1Ch],eax
0040C288   mov         ecx,dword ptr [ebp-1Ch]
0040C28B   mov         dword ptr [ebp-8],ecx
33:       base1* p1 = pderived;
0040C28E   mov         edx,dword ptr [ebp+8]
0040C291   mov         dword ptr [ebp-0Ch],edx      [9]
34:       p1->i = 1;
0040C294   mov         eax,dword ptr [ebp-0Ch]
0040C297   mov         ecx,dword ptr [eax]
0040C299   mov         edx,dword ptr [ecx+4]        [10]
0040C29C   mov         eax,dword ptr [ebp-0Ch]
0040C29F   mov         dword ptr [eax+edx],1
35:       base2* p2 = pderived;
0040C2A6   cmp         dword ptr [ebp+8],0
0040C2AA   je          f+87h (0040c2b7)
0040C2AC   mov         ecx,dword ptr [ebp+8]
0040C2AF   add         ecx,4                                 [11]
0040C2B2   mov         dword ptr [ebp-20h],ecx
0040C2B5   jmp         f+8Eh (0040c2be)
0040C2B7   mov         dword ptr [ebp-20h],0
0040C2BE   mov         edx,dword ptr [ebp-20h]
0040C2C1   mov         dword ptr [ebp-10h],edx      [12]
36:       p2->j = 1;
0040C2C4   mov         eax,dword ptr [ebp-10h]
0040C2C7   mov         ecx,dword ptr [eax]
0040C2C9   mov         edx,dword ptr [ecx+8]        [13]
0040C2CC   mov         eax,dword ptr [ebp-10h]
0040C2CF   mov         dword ptr [eax+edx],1
37:       int k = pderived->i;
0040C2D6   mov         ecx,dword ptr [ebp+8]
0040C2D9   mov         edx,dword ptr [ecx]
0040C2DB   mov         eax,dword ptr [edx+4]        [14]
0040C2DE   mov         ecx,dword ptr [ebp+8]
0040C2E1   mov         edx,dword ptr [ecx+eax]      [15]
0040C2E4   mov         dword ptr [ebp-14h],edx
38:       k = pderived->j;
0040C2E7   mov         eax,dword ptr [ebp+8]
0040C2EA   mov         ecx,dword ptr [eax]
0040C2EC   mov         edx,dword ptr [ecx+8]        [16]
0040C2EF   mov         eax,dword ptr [ebp+8]
0040C2F2   mov         ecx,dword ptr [eax+edx]
0040C2F5   mov         dword ptr [ebp-14h],ecx
39:
40:   }
0040C2F8   pop         edi
0040C2F9   pop         esi
0040C2FA   pop         ebx
0040C2FB   mov         esp,ebp
0040C2FD   pop         ebp
0040C2FE   ret

[1]dword ptr [ebp+8h]就是pderived,先看看是不是為NULL.
[2]dword ptr [ebp-18h]是一個中間變數,當pderived為NULL時,將其也賦為NULL
[3]取出__vbct_base1,其位置在derived類的開始處
[4]取出mostbast1類在derived中的位移,此值在_vbct_base1+4的位置,佔用4個位元組,其值為8, 因為derived前有兩個__vbct_prt,都為4位元組,故mostbast1在derived的位移為8.
[5]將pbase1賦值,dword ptr [ebp-4]存放pbase1;
[6]同(2),只是中間變數的地址不同
[7]同(3),取出__vbct_base1
[8]同(4), 取出mostbast2類在derived中的位移,此時為12
[9]取出derived類中的base1的地址,也就是derived中__vbct_base1的地址,可能你有疑問,看下面
[10]用p1存取資料時,還是通過__vbct_base1來做的,通過__vbct_base1得到mostbase1在derived中 的位移,最後得到的地址是pderived+8
[11]現在取出__vbct_base2的地址,看到了add ecx,4麼
[12]將p2賦值
[13]通過__vbct_base2來取得mostbase2的地址,再來存取j
[14]通過__vbct_base1來取得mostbase1的地址
[15]位移在eax中,取出i來
[16]通過__vbct_base1來取得mostbase2的地址

以下是我構想的c偽碼,可能不太正確,因為彙編代碼已經最佳化過
void f(derived* pderived)
{
 ----mostbase1* pbase1 = pderived;
 mostbase1 *pbase1,*temp1;
 if (pderived == 0)
 {
  temp1 = 0;
 }
 else
 {
  temp1 = (mostbase1*)(pderived+(pderived->__vbct_base1[1]));
 }
 pbase1 = temp1;

 ----mostbase2* pbase2 = pderived;
 mostbase2 *pbase2,*temp2;
 if (pderived == 0)
 {
  temp2 = 0;
 }
 else
 {
  temp2 = (mostbase2*)(pderived+(pderived->__vbct_base1[2]));
 }
 pbase2 = temp2;
 ----base1* p1 = pderived;
 base1* p1 = &pderived->__vbct_base1;
 ----p1->i = 1;
 (mostbase1*)(p1+p1->__vbct_base1[1])->i = 1;
 ----base2* p2 = pderived;
 base2* p2 = &pderived->__vbct_base2;
 ----p2->j = 1;
 (mostbase2*)(p2+p2->__vbct_base2[2])->j = 1;
 ----int k = pderived->i;
 int k = (mostbase1*)(pderived+pderived->__vbct_base1[1])->i;
 ----k = pderived->j;
 k = (mostbase2*)(pderived+pderived->__vbct_base1[2])->j;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.