• 虚函数


    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();            
        }                
                        
    }                   
    虚表的结构:
     
     
     
     
     
  • 相关阅读:
    adb命令之adb install
    GNU make and Makefile
    Makefile经典教程(掌握这些足够)
    Android.mk简介
    PhoneFactory.getDefaultPhone must be called from Looper thread
    Android源码目录结构
    软件部通用技术类网站名录
    β测试
    α测试
    白盒测试
  • 原文地址:https://www.cnblogs.com/ShiningArmor/p/11940163.html
Copyright © 2020-2023  润新知