zoukankan      html  css  js  c++  java
  • 虚函数

    1.关于虚函数
    在名函数前加关键字“virtual”的函数为虚函数;
    例如:class Base            
    {            
    public:            
        void Function_1()            
        {            
            printf("Function_1...
    ");            
        }            
        virtual void Function_2()   //虚函数         
        {            
            printf("Function_2...
    ");            
        }            
    };    
    反汇编分析:
    可以看到:
        通过对象调用时,virtual函数与普通函数都是E8 Call  
        通过指针调用时,virtual函数是FF Call,也就是间接Call 
            pe的IAT表使用的就是FF Call ;
            使用间接call的原因是因为虚函数的地址不靠谱,可能被改掉;   
            比如,子类覆盖父类函数时;
     
    1)虚函数的特点
    #include "stdafx.h"
        class Base                     
        {      
        public:    
            int x;
            int y;
            Base(){
                x=1;
                y=2;
            }
            void fun(){
            }
            virtual fun2(){
            }
        };                      
                            
        int main(int argc, char* argv[])                    
        {                    
            Base b;
            Base* pb = &b;
            pb ->fun2();
     
            getchar();
            return 0;                
        }                         
    测试上面结构的大小:Base base;            
    printf("%x
    ",sizeof(base));    
     结果是:0x0c;
    普通函数放结构体里面时,不会影响结构体大小,结构大小应该是两个int的大小8个字节;
    但在结构体中有一个或多个虚函数时,多了4个字节;
     
    反汇编分析:
     调用结构体里面的函数时,会用ecx传递this指针;
    this指针指向的就是对象的结构体;
    可以看到:有虚函数的对象的结构体中在结构体开始处多了4个字节,存放的是42501c是一个地址,这个地址就是虚函数表的地址;      
    将42501c存入edx,然后FF call这个地址;
     
    如果有多个虚函数反汇编:
     可以看到,第一个虚函数call的是[edx],第二个虚函数call的是[edx+4];
     
    总结:                            
        1、当类中有虚函数时,会多一个属性,4个字节                            
        2、多出的属性是一个地址,指向一张表,里面存储了所有虚函数的地址                            
     
    2.解析虚表信息
    class Base                    
    {                    
    public:                    
        int x;                
        int y;                
        virtual void Function_1()                    
        {                    
            printf("Function_1...
    ");                    
        }                    
        virtual void Function_2()                    
        {                    
            printf("Function_2...
    ");                    
        }                    
        virtual void Function_3()                    
        {                    
            printf("Function_3...
    ");                    
        }                    
    };                    
                        
    void TestMethod()                    
    {                    
        //查看 Sub 的虚函数表                
        Base base;                    
                        
        //对象的前四个字节就是虚函数表                
        printf("base 的虚函数表地址为:%x
    ",*(int*)&base);                
                        
        //通过函数指针调用函数,验证正确性                
        typedef void(*pFunction)(void);                    
                        
        pFunction pFn;                
                        
        for(int i=0;i<3;i++)                
        {                
            int temp = *((int*)(*(int*)&base)+i);            
            pFn = (pFunction)temp;            
            pFn();            
        }                
                        
    }                   
    虚表的结构:
     
     
     
     
     
  • 相关阅读:
    iPhone UIImage扩展方法,支持放大和旋转
    UIApplication
    ios定制键盘
    获取iOS设备当前ip地址
    类似长按图标抖动一样
    详解Objectivec Block应用
    如何开启AltiGen客户端log
    如何注册开通真正支付全世界190个国家和地区,多种货币(美元等)支付和收款国际版paypal帐户
    最新最牛!功能最多的四角号码在线查询
    DNN与SharePoint / Exchange /多站点/网站 并存一台服务器的方法
  • 原文地址:https://www.cnblogs.com/ShiningArmor/p/11940163.html
Copyright © 2011-2022 走看看