基本概念:

  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. git团队合作开发流程

    关于git的环境配置在以前已说过就不罗索了,这里介绍在公司如何团队一起开发项目 首先你需要把你的秘钥给管理员,如何配置以前介绍过了就不说了 进入正题:git ls-files查看当前厂库被add得所有 ...

  2. div的onblur事件

    一般情况下,onblur事件只在input等元素中才有,而div却没有,因为div没有tabindex属性,所以要给div加上此属性. 如: <div tabindex="0" ...

  3. 通过js获取元素css3的transform rotate旋转角度方法

    我们再试用jquery获取样式的时候是通过$('domName').css('transform'):的方式来获取元素的css样式,但是通过它获取到的css3的transform属性是以矩阵的方式呈现 ...

  4. linux之shell编程基本语法

    Shell是用户与内核进行交互操作的一种接口,目前最流行的Shell称为bash Shell.Shell也是一门编程语言<解释型的编程语言>,即shell脚本<就是在用linux的s ...

  5. [笔记]RankSVM 和 IR SVM

    之前的博客:http://www.cnblogs.com/bentuwuying/p/6681943.html中简单介绍了Learning to Rank的基本原理,也讲到了Learning to R ...

  6. Python 多进程概述

    multiprocessing python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Python提供了非常好用的多进程包mult ...

  7. [UWP]了解模板化控件(5):VisualState

    1. 功能需求 使用TemplatePart实现上篇文章的两个需求(Header为空时隐藏HeaderContentPresenter,鼠标没有放在控件上时HeaderContentPresent半透 ...

  8. MySQL Online DDL的改进与应用

        本文简析Online DDL的实现原理与使用过程注意事项.       任何DDL操作,执行者都需要预先测试或者清晰了解这个操作会给数据库带来的影响是否是在业务期间数据库的可承受范围内,尤其是 ...

  9. node.js系列(模块):request模块实现与php的通讯

    app.js: var express = require('express'); var request = require('request'); var app = express(); /*r ...

  10. 如何解决chrome 等浏览器不支持本地ajax请求的问题

    XMLHttpRequest cannot load file:///D:/WWW/angularlx/ui-router-test/template/content.html. Cross orig ...