基本概念:

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

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

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

函数调用:

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

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

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

class Person {
private:
int value;
public:
Person():value(){}
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(); // result 为 130
result = &p->*pf();   // 语法与上句一样
}

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

class Person {
private:
int value;
public:
Person():value(){}
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(); // 崩了,因为没有this指针
} /*以下是老师提供的代码,但是也崩了*/
void main() {
Person p, *pp;
pp = &p;
PFUNC pf = (PFUNC)**(int **)pp; // 通过虚函数表获得虚函数pf
__asm mov ecx, pp           // 传入this指针
int result = pf(); // 还是崩了
}

 

对于第三种方式,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指针是类模板装载入内存时的模板首地址,显然它没有初始化。

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

使用函数指针调用C++虚函数的更多相关文章

  1. TControl的显示函数(5个非虚函数,4个虚函数)和三个例子的执行过程(包括SetParent的例子)

    // 9个显示函数 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); virtual; // 虚函数,important 根据父控 ...

  2. c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解

    静态多态.动态多态 静态多态:程序在编译阶段就可以确定调用哪个函数.这种情况叫做静态多态.比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数.动态多态:在运行期间才可以确定最终调用的 ...

  3. 【转】C#传委托给C的函数指针调用问题

    C#传委托给C的函数指针调用问题C代码如下: #include "stdio.h" __declspec(dllexport) int Call(int (*qq)(int num ...

  4. keil 中用函数指针调用函数的参数限制

    NSIC中,通过函数指针调用的函数的参数的个数没有限制,但是KeilC对此有限制,至多3个参数.因为,KeilC编译时,无法通过函数指针找到该函数的局部数据段,也就无法通过局部数据段传递参数,只能通过 ...

  5. 不要在基类析构函数中调用纯虚函数,否则运行时会报错“pure virtual method called”

    如上. 这是因为:delete派生类对象时,先调用派生类的析构函数,然后再调用基类的析构函数:此时如果调用纯虚函数的话,派生类的对象已经被破坏了,所以会报错. http://www.cnblogs.c ...

  6. C++中为什么构造函数不能是虚函数,析构函数是虚函数

    一, 什么是虚函数? 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离:用形象的语 ...

  7. 类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)

    原理分析 当调用一个虚函数时, 编译器生成的代码会调用 虚表地址[0](param1, param2)这样的函数. 已经不是在调用函数名了. 当我们将虚表地址[n]中的函数实现改为另外的函数, 虚函数 ...

  8. C++中对C的扩展学习新增内容———面向对象(继承)函数扩展性及虚函数机制

    1.c语言中的多态,动态绑定和静态绑定 void do_speak(void(*speak)()) { speak(); } void pig_speak() { cout << &quo ...

  9. C++虚函数【Java有虚函数吗?】

    1,简单介绍 定义在基类中的函数,子类必须对其进行覆写![必须对其进行覆写?!]——Java中的接口.Abstract方法中的抽象类也有这样的要求. C++中定义: virtual void deal ...

随机推荐

  1. shiro使用教程

    一.shiro是什么 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码学和会话管理.不仅可以在Web项目中使用,在普通的项目中也是可以使用的 二.shiro可以做什 ...

  2. Docker系列一之基础快速入门企业实战

    1.1什么是LXC LXC为Linux Container的简写.Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚 ...

  3. 使用VB6写一个自定义的进度信息框窗口

    一.起因说明 之前有些项目是用Access完成的,当时为了给用户显示一些进度信息,自制了一个进度信息窗体,类似下图所示: 随着项目不断变迁,需要将进度信息按阶段及子进度进行显示,并且出于代码封装的需求 ...

  4. java复习(4)---数字处理类

    java本身自带一些封装好的类方便数字问题的处理,review下方便以后使用 DecimalFormat类 可格式化数字格式,控制输出格式 Math类 提供三角函数.指数函数.取整函数.最大最小函数. ...

  5. 使用charles抓取htpps的方法

    自己整理的步骤做个记录 1.下载证书,官方地址:http://www.charlesproxy.com/ssl.zip 可直接点击链接下载:http://charlesproxy.com/getssl ...

  6. Windows 和 Mac 系统下安装git 并上传,修改项目

    首先在MAC上怎么操作. 在gitHub创立一个账户,在创立一个项目,这就不用我说了对吧. 创建完之后是这样的: 接下来,我们打开https://brew.sh 这是下载homebrew的网站,hom ...

  7. JAVAEE规范基础知识

    JavaEE规范基础知识 本人博客文章网址:https://www.peretang.com/basic-knowledge-of-javaee-standard/ JavaEE简介 JavaEE,J ...

  8. select效果联动

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  9. Python中使用Mysql(安装篇)

    准备工作 import MySQLdb Linux系统自带了Python,但并不是都有这个包,至少我每次拿到一台全新的服务器时候,都发现没有装这个包. 这个东西的下载地址是 http://source ...

  10. JQuery 根据ID在页面中定位

    1.锚点跳转简介 锚点其实就是可以让页面定位到某个位置上的点.在高度较高的页面中经常见到.比如百度的百科页面,wiki中的page内容. 我知道实现锚点的跳转有两种形式,一种是a标签+name属性:还 ...