虚函数

一、 直接调用和间接调用

汇编中:
call 地址 是直接调用 ,或者 E8。。。
call [。。。] 是间接调用 ,或者FF。。。

二、虚函数表:

	class Base			
	{			
	public:			
	    void Function_1()			
	    {			
	        printf("Function_1...\n");			
	    }			
	    virtual void Function_2()			
	    {			
	        printf("Function_2...\n");			
	    }			
	};	

对象调用时,没有任何区别

	Base base;			
				
	base.Function_1();			
	00401090 8D 4D FC             lea         ecx,[ebp-4]			
	00401093 E8 9F FF FF FF       call        @ILT+50(Base::Function_1) (00401037)			
				
	base.Function_2();			
	00401098 8D 4D FC             lea         ecx,[ebp-4]			
	0040109B E8 65 FF FF FF       call        @ILT+0(Base::Function_2) (00401005)	

指针调用

Base base;			
Base* pb = &base;			
			
pb->Function_1();			
004010A6 8B 4D F8             mov         ecx,dword ptr [ebp-8]			
004010A9 E8 89 FF FF FF       call        @ILT+50(Base::Function_1) (00401037)			
			
pb->Function_2();			
004010AE 8B 4D F8             mov         ecx,dword ptr [ebp-8]			
004010B1 8B 11                mov         edx,dword ptr [ecx]			
004010B3 8B F4                mov         esi,esp			
004010B5 8B 4D F8             mov         ecx,dword ptr [ebp-8]			
004010B8 FF 12                call        dword ptr [edx]	

1、通过对象调用时,virtual函数与普通函数都是E8 Call
2、通过指针调用时,virtual函数是FF Call,也就是间接Call

三、虚函数大小

	class Base			
	{			
	public:			
	    int x;			
	    int y;			
	    virtual void Function_1()			
	    {			
	        printf("Function_1...\n");			
	    }			
	    virtual void Function_2()			
	    {			
	        printf("Function_2...\n");			
	    }			
	};		
	
	Base base;			
			
	printf("%x\n",sizeof(base));			//12     虚函数4个字节(不管多少个)
			

多出来的4个字节在对象的首地址

								
	pb->Function_1();							
	0040D9E3 8B 4D F0             mov         ecx,dword ptr [ebp-10h]							
	0040D9E6 8B 11                mov         edx,dword ptr [ecx]							
	0040D9E8 8B F4                mov         esi,esp							
	0040D9EA 8B 4D F0             mov         ecx,dword ptr [ebp-10h]							
	0040D9ED FF 12                call        dword ptr [edx]							
								
								
	pb->Function_2();							
	0040D9F6 8B 45 F0             mov         eax,dword ptr [ebp-10h]							
	0040D9F9 8B 10                mov         edx,dword ptr [eax]							
	0040D9FB 8B F4                mov         esi,esp							
	0040D9FD 8B 4D F0             mov         ecx,dword ptr [ebp-10h]							
	0040DA00 FF 52 04             call        dword ptr [edx+4]	

1、当类中有虚函数时,会多一个属性,4个字节

2、多出的属性是一个地址,指向一张表,里面存储了所有虚函数的地址

四、虚函数的值

	class Base					
	{					
	public:					
		int x;				
		int y;				
	    virtual void Function_1()					
	    {					
	        printf("Function_1...\n");					
	    }					
	    virtual void Function_2()					
	    {					
	        printf("Function_2...\n");					
	    }					
	    virtual void Function_3()					
	    {					
	        printf("Function_3...\n");					
	    }					
	};					
																	
	void TestMethod()					
	{					
		//查看 Sub 的虚函数表				
	    Base base;					
						
		//对象的前四个字节就是虚函数表				
		printf("base 的虚函数表地址为:%x\n",*(int*)&base);				
						
		//通过函数指针调用函数,验证正确性				
	    typedef void(*pFunction)(void);					
						
		pFunction pFn;				
		int temp = *((int*)(*(int*)&base)+0);							
	}																					

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值