基本概念:

  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. Lvs+keepalived+mysql主从热备

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...

  2. 老李分享:Python开发性能测试脚本

    老李分享:Python开发性能测试脚本   测试开发工程师的工作主要是根据测试目标来完成,帮助测试人员完成测试目标,测试的业务需求是测试人员提出,但是由于环境的制约,手中没有性能测试工具的时候,性能测 ...

  3. 移动端WEBAPP开发遇到的坑,以及填坑方案!持续更新~~~~

    前言:在移动端WEBAPP开发中会遇到各种各样的问题,通过此文对遇到的问题做一个归纳总结,方便自己日后查询,也给各位前端开发友人做一个参考.   此文中涉及的问题是本人开发中遇到的,解决方案是本人思考 ...

  4. Jquery对raido的一些操作方法

    raido 单选组radio:   $("input[type=radio][checked]").val(); 获  取一组radio被选中项的值 var item = $('i ...

  5. grid实例(Asp.net)

    <link href="../../js/jqGrid/css/ui.jqgrid.css" rel="stylesheet" type="te ...

  6. python os模块常用方法

    OS模块是Python标准库中的一个操作模块,主要用于处理Linux操作系统中的文件和目录 1.要使用OS必须先导入OS import os 2.os.getcwd()获取当前路径. print os ...

  7. 使用vs2015搭建Asp.net Core

    准备工具    1.首先得安装vs2015 并且升级至 update3及以上  2.安装.net core sdk.附上官网下载地址 http://www.microsoft.com/net/down ...

  8. Reids详解-抄本

    1.redis是什么 Redis 是一个基于内存的高性能key-value数据库.是一个开源的.使用C语言编写的.支持网络交互的.可基于内存也可持久化的Key-Value数据库. 2.redis的特点 ...

  9. 你想要的都在这里,ASP.NET Core MVC四种枚举绑定方式

    前言 本节我们来讲讲在ASP.NET Core MVC又为我们提供了哪些方便,之前我们探讨过在ASP.NET MVC中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满 ...

  10. Java中的集合与线程的Demo

    一.简单线程同步问题 package com.ietree.multithread.sync; import java.util.Vector; public class Tickets { publ ...