类、虚函数分析

原创 2012年03月31日 14:55:39

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

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的。

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

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导 白杨 http://baiy.cn   “在正确的场合使用恰当的特性” 对称职的C++程序员来说是一个基本标准。想要做到这点,首先要...

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导

分析c++RTTI较好的文章

虚函数在基类和子类中都存在时,调用情况分析

首先,给出基类animal和子类fish //============================================================== // ...

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导

“在正确的场合使用恰当的特性” 对称职的C++程序员来说是一个基本标准。想要做到这点,首先要了解语言中每个特性的实现方式及其开销。本文主要讨论相对于传统 C 而言,对效率有影响的几个C++新特性。相对...

RTTI、虚函数和虚基类的实现方式、开销分析及使用指导

转自:http://baiy.cn/doc/cpp/inside_rtti.htm RTTI、虚函数和虚基类的实现方式、开销分析及使用指导 白杨 http://baiy.cn   “...

C++ 虚函数在基类与派生类对象间的表现及其分析

转载地址:http://www.cnblogs.com/Romi/archive/2013/09/18/3329132.html 近来看了侯捷的《深入浅出MFC》,读到C++重要性质中的虚函数与...

RTTI、虚函数和虚基类的开销分析及使用指导

转自:http://baiy.cn/ RTTI、虚函数和虚基类的开销分析及使用指导 白杨   “在正确的场合使用恰当的特性” 对称职的C++程序员来说是一个基本标准。想要做到这点,首先要了解语言中...

RTTI、虚函数和虚基类的开销分析及使用指导

运行时开销恐怕是程序员最关心的问题之一了。相对与传统C程序而言,C++中有可能引入额外运行时开销的新特性包括: 虚基类虚函数RTTI(dynamic_cast和typeid)异常对象的构造和析构...

虚基类与虚函数

  • 2014-10-09 21:57
  • 1.46MB
  • 下载

纯虚函数和抽象类的实例

  • 2015-04-14 19:33
  • 1.67MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)