分析虚函数

 其实虚函数在编译器中的实现是非常简单的,直接翻vc2005编译出来的汇编便可以知道。
比如下个程序:
C/C++ code
   
   
#include < iostream > using namespace std; class ABC { public : virtual void a(){ cout << " ABC::a " << endl;} virtual void b(){ cout << " ABC::b " << endl;} }; class CDE { public : virtual void a(){ cout << " CDE::a " << endl;} virtual void b(){cout << " CDE::b " << endl;} }; int main() { CDE * p = new CDE; ABC * q = (ABC * )p; p -> a(); p -> b(); delete p; return 0 ; }

p->a()
p->b()所对应的源代码是:
Assembly code
   
   
p->a(); 00411573 mov eax,dword ptr [p] ;p开始的四个字节是存放虚函数表地址 00411576 mov edx,dword ptr [eax] ;edx中存放虚函数表的第一项地址,就是a的地址 00411578 mov esi,esp ;debug用,不管它 0041157A mov ecx,dword ptr [p] ;this指针放入ecx,作为参数传给成员函数 0041157D mov eax,dword ptr [edx] ;将edx所指向的函数地址移动入eax 0041157F call eax ;调用函数 00411581 cmp esi,esp ;debug用的 00411583 call @ILT+440(__RTC_CheckEsp) (4111BDh) p->b(); 00411588 mov eax,dword ptr [p] 0041158B mov edx,dword ptr [eax] 0041158D mov esi,esp ;debug用 0041158F mov ecx,dword ptr [p] ;this指针放入ecx,作为参数传给成员函数 00411592 mov eax,dword ptr [edx+4] ;b是第二个声明的虚函数,因此相应的在虚函数表中[edx+4]是b的函数地址 00411595 call eax 00411597 cmp esi,esp 00411599 call @ILT+440(__RTC_CheckEsp) (4111BDh)

编译的时候便已经为每个类确定好了虚函数表,并且将其地址放在类的开头4个字节。
因此,所谓的调用虚函数的开销即是指多了两次访问内存的操作:一次是访问虚函数表,第二次是从虚汗数表中得到实际函数的地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值