浅析C++中虚函数的调用及对象的内部布局2 (来自:lizhe1985)

下面通过分析类CDerived的非虚成员函数Fun2()来证明上面图中虚函数表指针的存在。

void CDerived::Fun2()

{

004118F0 push ebp

004118F1 mov ebp,esp

004118F3 sub esp,0CCh

004118F9 push ebx

004118FA push esi

004118FB push edi

004118FC push ecx

004118FD lea edi,[ebp-0CCh]

00411903 mov ecx,33h

00411908 mov eax,0CCCCCCCCh

0041190D rep stos dword ptr es:[edi]

0041190F pop ecx

00411910 mov dword ptr [ebp-8],ecx

m_iValue1 = 13;

00411913 mov eax,dword ptr [this] // 6

00411916 mov dword ptr [eax+4],0Dh // 7

m_iValue2 = 13;

0041191D mov eax,dword ptr [this]

00411920 mov dword ptr [eax+8],0Dh

}

00411927 pop edi

00411928 pop esi

00411929 pop ebx

0041192A mov esp,ebp

0041192C pop ebp

0041192D ret

上面是类CDerived的非虚成员函数Fun2()的汇编代码。可以看到,行6是将this指向的地址放入eax寄存器,而行7是给this指针指向的地址加4的地址赋值(具体的分析,可以看《浅析C++中的this指针》),而这个地址里面存放的是类CDerived的第一个成员变量。我们知道this指针是指向对象首地址的,那么为什么要给第一个成员变量赋值的时候要向后移动4个字节?答案是因为对象的前4个字节是用来存放虚表指针的。

下面的代码是《浅析C++中的this指针》一文中的不含虚函数的类的C++代码和编译后的汇编代码:

class CTest

{

public:

void SetValue();

private:

int m_iValue1;

int m_iValue2;

};

void CTest::SetValue()

{

m_iValue1 = 13;

m_iValue2 = 13;

}

void CTest::SetValue()

{

004117E0 push ebp

004117E1 mov ebp,esp

004117E3 sub esp,0CCh

004117E9 push ebx

004117EA push esi

004117EB push edi

004117EC push ecx

004117ED lea edi,[ebp-0CCh]

004117F3 mov ecx,33h

004117F8 mov eax,0CCCCCCCCh

004117FD rep stos dword ptr es:[edi]

004117FF pop ecx

00411800 mov dword ptr [ebp-8],ecx

m_iValue1 = 13;

00411803 mov eax,dword ptr [this] // 8

00411806 mov dword ptr [eax],0Dh // 9

m_iValue2 = 13;

0041180C mov eax,dword ptr [this]

0041180F mov dword ptr [eax+4],0Dh

}

00411816 pop edi

00411817 pop esi

00411818 pop ebx

00411819 mov esp,ebp

0041181B pop ebp

0041181C ret

通过行8、行9和行6、行7的比较就可以看出:类CTest的对象前4个字节存放的是自己的第一个成员变量;而类CDerived的对象从第5个字节开始才是存放的自己的第一个成员变量,它的前4个字节是用来存放虚表指针的。这再一次证明了上面图中对象内部布局的正确性。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值