zoukankan      html  css  js  c++  java
  • 使用函数指针调用C++虚函数

    基本概念:

      1. 函数指针,一个地址指针变量,其值指向代码区的某个函数首地址。

      2. 虚函数,可以被子类覆写的C++成员函数。由虚函数表实现。

      3. 虚函数表指针(vpt),指向虚函数表首地址的指针,一般放在类实例的首4字节(x86系统)。通过它能找的虚函数表,进而能找的某个虚函数。

    函数调用:

      1. C++函数的普通调用方式:      

    class Person {
    private:
       int value;
    public:
       Person():value(100){} 
       virtual int getValue(int a) {
           return value + a;         
       }  
    };
    
    void main() {
      Person p;
      int result = p.getValue(30);    // result 为 130
    }

      2. 使用普通函数指针调用:

    class Person {
    private:
       int value;
    public:
       Person():value(100){} 
       virtual int getValue(int a) {
           return value + a;         
       }  
    };
    
    typedef int (Person::PFUNC) (int);    // 定义函数指针类型
    
    void main() {
      PFUNC pf = &Person::getValue;      // 定义变量
      Person p;
      // int result = p.getValue(30);    
      int result = p.*pf(30);               // result 为 130
      result = &p->*pf(30);                // 语法与上句一样
    }

      3. 使用函数指针外部调用

    class Person {
    private:
       int value;
    public:
       Person():value(100){} 
       virtual int getValue(int a) {
           return value + a;         
       }  
    };
    
    typedef int (PFUNC) (int);    // 定义函数指针类型
    
    void main() {
      Person p, *pp;
      pp = &p;
      PFUNC pf = (PFUNC)**(int **)pp;  // 通过虚函数表获得虚函数pf
      int result = pf(30);               // 崩了,因为没有this指针
    }
    
    /*以下是老师提供的代码,但是也崩了*/
    void main() {
      Person p, *pp;
      pp = &p;
      PFUNC pf = (PFUNC)**(int **)pp;    // 通过虚函数表获得虚函数pf
      __asm mov ecx, pp           // 传入this指针
      int result = pf(30);               // 还是崩了
    }

     

    对于第三种方式,this指针传不进去,然后一直报错:

      The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

      如果我把getValue函数换成无参的,两种方法都可以调用。但是结果第一种是随机数,第二种是100。可见第二种通过汇编方式确实传进去了this指针,(在有多继承时这个this指针一般会做调整的),第一种随机数的原因是它的this指针是类模板装载入内存时的模板首地址,显然它没有初始化。

      回到上题,我还在纠结于怎么传参!

  • 相关阅读:
    Spring.NET企业架构实践之 NHibernate + Spring.NET + WCF + Windows服务 + Silverlight 中小企业应用架构完整Demo
    UnitOfWork模式和Repository模式[转]
    倾情奉献:开源企业类库(EntLib)大分享
    Spring.NET企业架构实践之Nhibernate + WCF + ASP.NET MVC + NVelocity 对PetShop4.0重构(一)——架构设计
    WCF服务
    EA使用教程
    第三方支付接口,银行接口(附下载),third party bank interface
    ASP.NET 开发 WAP 网站
    开源软件Mono框架和架构
    wcf asp.net
  • 原文地址:https://www.cnblogs.com/skimoon/p/3892191.html
Copyright © 2011-2022 走看看