Cpp 对象模型探索 / 虚函数的调用方式

虚函数有两种调用方式:

  • 方案1,直接使用函数地址调用。
  • 方案2,通过对象的虚函数表指针找到虚函数表,从而得到函数地址,完成调用。

应用场景主要有如下三种情况:

  1. 当对象直接调用时,采用方案 1 调用虚函数。
  2. 当对象的指针或者引用调用时,采用方案 2 调用虚函数。
  3. 类成员函数中调用虚函数。

(1)若是直接调用,则走方案 2 路线。

(2)若是使用 类名::虚函数,则走方案 1 路线。                                         

栗子:

class CBase
{
public:
	virtual void func() { std::cout << "CBase::func()" << std::endl; }
};

class CA : public CBase
{
public:
	void func() { std::cout << "CA::func()" << std::endl; }
	void func_1() { CBase::func(); }
	void func_2() { func(); }
};

(1)当执行如下代码时,

CA A;
A.func();
CBase Base;
Base.func();

结果为

CA::func()
CBase::func()

转成汇编,

005D29F6  call        CA::func (05D1325h)  
005D29FE  call        CBase::CBase (05D11F9h) 

 可以发现,编译器采用的是直接调用的方式,与场景1相对应。

(2)当执行如下代码时,

CBase* pbase = new CA;
pbase->func();

结果为

CA::func()

转成汇编, 

    27: 	pbase->func();
005D2A8D  mov         eax,dword ptr [pbase]  
005D2A90  mov         edx,dword ptr [eax]  
005D2A92  mov         esi,esp  
005D2A94  mov         ecx,dword ptr [pbase]  
005D2A97  mov         eax,dword ptr [edx]  
005D2A99  call        eax  
005D2A9B  cmp         esi,esp  
005D2A9D  call        __RTC_CheckEsp (05D12F3h)  

 执行的方案是通过对象的虚函数表指针找到虚函数表,从而得到函数地址,完成调用。与场景2相对应。

(3)执行如下代码,

A.func_1();
A.func_2();

结果为

CBase::func()
CA::func()

 转成汇编,

    17: 		CBase::func(); 
0071284D  mov         ecx,dword ptr [this]  
00712850  call        CBase::func (071120Dh)

    21: 		func(); 
007128AD  mov         eax,dword ptr [this]  
007128B0  mov         edx,dword ptr [eax]  
007128B2  mov         esi,esp  
007128B4  mov         ecx,dword ptr [this]  
007128B7  mov         eax,dword ptr [edx]  
007128B9  call        eax  
007128BB  cmp         esi,esp  
007128BD  call        __RTC_CheckEsp (07112F3h)  

可以发现,前者是直接调用的方式 ,后者是通过虚函数表才找到的虚函数的地址。与场景3相对应。

 

 

(SAW:Game Over!)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值