类、虚函数分析

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

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

 

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

c++类中的虚函数

类中虚函数的作用
  • u011484045
  • u011484045
  • 2015年07月13日 16:49
  • 957

c++ 类大小(含虚函数)

虽然很难找到一本不讨论多态性的C++书籍或杂志,但是,大多数这类讨论使多态性和C++虚函数的使用看起来很难。我打算在这篇文章中通过从几个方面和结合一些例子使读者理解在C++中的虚函数实现技术。说明一点...
  • FrankieWang008
  • FrankieWang008
  • 2011年12月20日 13:06
  • 2844

C++虚函数和拷贝的问题总结

引自 在C++中创立一个空类后,其实里面会自动生成一些内容,他们是:缺省构造函数,缺省拷贝构造函数 ,缺省析构函数,缺省取址运算符,和缺省赋值运算符。但在某些情况下,我们需要自定义这些函数。其中,为...
  • qianqin_2014
  • qianqin_2014
  • 2016年04月11日 10:30
  • 586

获取C++类成员虚函数地址

1.GCC平台GCC平台获取C++成员虚函数地址可使用如下方法[1]^{[1]}:class Base{ int i; public: virtual void f1(){ ...
  • K346K346
  • K346K346
  • 2017年02月21日 16:54
  • 788

【c++基础】虚函数的使用以及和成员函数的区别

前言一直以来都知道虚函数的经典用法,但是除了本科时刚学c++的时候了解过,后来因为做不同的项目在不同的语言之间跳转(自觉都是浅尝辄止),这些基本的东西都忘记了,现在重拾并记录,权当巩固基础了。经典用法...
  • XiaoHeiBlack
  • XiaoHeiBlack
  • 2016年11月01日 14:11
  • 921

C++类对象大小的计算(二)含有虚函数类大小计算

以下内存测试环境为Win7+VS2012
  • gongtxy
  • gongtxy
  • 2014年10月01日 15:54
  • 1054

用虚函数或者bind、function实现线程的方法

应用:Thread封装 在实现自定义的线程类时,曾经这么干过:定义虚函数run(),用户自定义的CustomThread::Thread后,自己实现run()函数就OK了。 当时觉得这么做也不错。 ...
  • jiangdewei2012
  • jiangdewei2012
  • 2014年05月13日 13:23
  • 292

c++中的虚函数、虚基类、类模板

一、虚函数 首先要明白C++为什么要引进虚函数这个机制, 虚函数就是在基类中被关键字virtual说明,并在派生类中重新定义的函数。虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过...
  • zyazky
  • zyazky
  • 2016年08月15日 14:17
  • 1647

关于空类,含有虚函数的类的大小

1、为何空类的大小不是0呢? 为了确保两个不同对象的地址不同,必须如此。 类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的二地址。同样,空类也会实例化,所以编译器会给空类隐含的添加...
  • dahai_881222
  • dahai_881222
  • 2012年08月12日 11:04
  • 1877

虚函数 类空间占用大小

总结一下VPTR 和 VTABLE 和类对象的关系:        每一个具有虚函数的类都有一个虚函数表VTABLE,里面按在类中声明的虚函数的顺序存放着虚函数的地址,这个虚函数表VTABLE是这个...
  • maxiaozhuang
  • maxiaozhuang
  • 2014年09月23日 10:07
  • 1014
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:类、虚函数分析
举报原因:
原因补充:

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