关闭

类、虚函数分析

417人阅读 评论(0) 收藏 举报

对于虚函数,虽然一直知道怎么用,但是对其内部机制却不清楚。今天写了小段程序然后反汇编:

class CBase
{
public:
virtual void vfun(){};
void         fun(){};
};

class CTest:public CBase
{
virtual void vfun(){};
void         fun(){};
};
void main()
{
CTest  pTest;
CBase *pBase;
pBase = &pTest;
pBase->fun();
pBase->vfun();
return;
}

对以上反汇编后的关键代码是:

void main()
{
013D1400  push        ebp 
013D1401  mov         ebp,esp 
013D1403  sub         esp,0D8h 
013D1409  push        ebx 
013D140A  push        esi 
013D140B  push        edi 
013D140C  lea         edi,[ebp-0D8h] 
013D1412  mov         ecx,36h 
013D1417  mov         eax,0CCCCCCCCh 
013D141C  rep stos    dword ptr es:[edi] 
CTest  pTest;
013D141E  lea         ecx,[pTest] 
013D1421  call        CTest::CTest (13D11F9h)  //13D11F9h是类CTest构造函数在内存中的地址
CBase *pBase;
pBase = &pTest;
013D1426  lea         eax,[pTest] 
013D1429  mov         dword ptr [pBase],eax  //这两句是将pTest的地址放入pBase代表的内存空间中
pBase->fun();
013D142C  mov         ecx,dword ptr [pBase] 
013D142F  call        CBase::fun (13D118Bh)  //这是调用的普通函数,直接调用的CBase的fun(13D118Bh是CBase的fun在内存中的地址)。
pBase->vfun();
013D1434  mov         eax,dword ptr [pBase] 
013D1437  mov         edx,dword ptr [eax] 
013D1439  mov         esi,esp 
013D143B  mov         ecx,dword ptr [pBase] 
013D143E  mov         eax,dword ptr [edx] 
013D1440  call        eax  //这一段时调用虚函数,可以看出是通过pTest的地址进行访问的,而pTest在代表的地址空间中存放的是一个虚函数表指针和内成员。
013D1442  cmp         esi,esp 
013D1444  call        @ILT+330(__RTC_CheckEsp) (13D114Fh) 
return;
}

结论:

类的成员函数是所有类共享的,是存放于代码段,而每个类的成员函数都有他特定的内存空间。当一个类实例化时,会分配一段内存空间存放成员变量,有意思的是当这个类有虚函数时,会默认的分配一个指针空间,该指针指向一个虚函数表。 当该实例进行函数调用时,如果是普通函数会直接调用该类的函数,如果是虚函数会通过该实例的指向虚函数表的指针进行对应的函数调用。

 

补充:

class CBase
{
public:
   
virtual void Test(int iTest = 0) const  = 0;
};

class CDerived : public CBase
{
public:
    
void Test(int iTest = 1) const { cout << iTest << endl; };
};

void Test()
{
    CBase
*p = new CDerived;

    p
->Test();

    delete p;
}

调试发现p->Test()虽然是调用的CDerived的,但是使用的缺省值却是CBase的。

所以缺省函数是属于静态绑定的。

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:133516次
    • 积分:1577
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:61篇
    • 译文:0篇
    • 评论:1条
    最新评论