C++中回调函数(CallBack)的使用
如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。
其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递this指针给其成员函数从而实现成员函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员。由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让this指针起作用,通过采用以下两种典型技术可以解决在C++中使用回调函数所遇到的问题。这种方法具有通用性,适合于任何C++。
1). 不使用成员函数,为了访问类的成员变量,可以使用友元操作符(friend),在C++中将该函数说明为类的友元即可。
2). 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果做不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。
这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。关于静态方法访问非静态变量和函数的方式请见http://www.cnblogs.com/this-543273659/archive/2011/08/29/2157966.html)
首先明白什么是回调函数:比如说被调函数void callbackf(int n){}要想作为回调函数的话,callbackf必须作为主调函数的形参出现,如void f(void (*p(int)),int n)形式才行!
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如果我要在static中调用类中的成员,怎么做?
我得定义一个全局的 指向该类的指针,然后在类的初始化函数里面将 类的this 指针赋值给该全局指针。
然后在static函数中通过该全局指针调用类的其它成员。
例子1:

#include "stdafx.h"
#include <iostream>
#include <assert.h>
using namespace std; class Test
{
public: friend void callBackFun(void){ cout << "CallBack Function!";} //友元函数作为回调函数 friend方式实现, //因为callBackFun默认有一个const Test* 的指针
}; typedef void (*FPtr)(void); void Fun(FPtr ptr)
{
ptr();
} int main(void)
{
Fun(callBackFun); return 0;
}
例2:
#include<iostream> using namespace std; class A { public: static void callback() //类的成员函数作为回调函数 static方式实现 { cout<<"回调函数开始执行了!"<<endl; } }; void f(void (*p)()) { p();
} int main() { void (*p)(); p=A::callback; f(p); return 0; }
还可以把f()函数设为类的成员函数:
#include<iostream> using namespace std; class A { public: static void callback() //类的成员函数作为回调函数 static方式实现 { cout<<"回调函数开始执行了!"<<endl; } void f(void (*p)()) { p();
} };
int main() { A a; void (*p)(); p=A::callback; a.f(p); return 0; }
///什么是回调函数
普通的函数是:咱们的函数调用系统的函数,
把你写的程序和系统已经封装好的函数看成两个部分
你的程序使用系统的函数 那叫 调用
系统函数使用你的程序函数 就叫回调
一般多用于系统函数与你的函数要进行异步处理
比如按键事件,其实是个消息
你的函数比按键事件更早存在
所以你要将这个函数做为回调函数提交给系统,
然后系统在接收到按键事件后,再调用你的函数
/////////////////////////////////////////////
比如:void fun(){printf();}
而回调函数是:系统调用你的函数。
win32 编程的WndProc,java的事件,c#的delegate都是这种思想。可以说没有坏处,回调使得系统更加灵活。
当 函数指针做为函数的参数,传递给一个被调用函数,
被调用函数就可以通过这个指针调用外部的函数,这就形成了回调 一般的程序中回调函数作用不是非常明显,可以不使用这种形式 最主要的用途就是当函数不处在同一个文件当中,比如动态库,要调用
其他程序中的函数就只有采用回调的形式 #include "stdio.h"
#include "conio.h" int add(int a, int b);
int libfun(int (*pDis)(int a, int b)); int main(void)
{
int (*pfun)(int a, int b); pfun = add;
libfun(pfun);//调用int libfun(int (*pDis)(int a, int b)) } int add(int a, int b)
{
return a + b; } int libfun(int (*pDis)(int a, int b))//回调add()函数
{
int a, b;
a = 1;
b = 2;
printf("%d", pDis(a, b)); } 现在这几个函数是在同一个文件当中 假如
int libfun(int (*pDis)(int a, int b))
是一个库中的函数,就只有使用回调了,通过函数指针参数将外部函数地址传入
来实现调用 函数 add 的代码作了修改,也不必改动库的代码,就可以正常实现调用
便于程序的维护和升级
C++中回调函数(CallBack)的使用的更多相关文章
- node.js 中回调函数callback(转载),说的很清楚,看一遍就理解了
最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs.express 的代码就会看得一塌糊涂.比如: 复制代码 代码如下: app.use(fu ...
- 理解javascript中的回调函数(callback)
以下内容来源于:http://www.jb51.net/article/54641.htm 最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs ...
- 解决有关flask-socketio中服务端和客户端回调函数callback参数的问题(全网最全)
由于工作当中需要用的flask_socketio,所以自己学习了一下如何使用,查阅了有关文档,当看到回调函数callback的时候,发现文档里都描述的不太清楚,最后终于琢磨出来了,分享给有需要的朋友 ...
- 理解javascript中的回调函数(callback)【转】
在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...
- Scrapy - Request 中的回调函数callback不执行
回调函数callback不执行 大概率是被过滤了 两种方法: 在 allowed_domains 中加入目标url 在 scrapy.Request() 函数中将参数 dont_filter=True ...
- js回调函数(callback)理解
Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函 ...
- java基础-回调函数(callback)
java基础-回调函数(callback) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数 ...
- C++回调函数(callback)的使用
什么是回调函数(callback) 模块A有一个函数foo,他向模块B传递foo的地址,然后在B里面发生某种事件(event)时,通过从A里面传递过来的foo的地址调用foo,通知A发生了什么事 ...
- Windows编程中回调函数的使用心得(MFC篇)
回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定 ...
随机推荐
- SQLServer—系统中的内存配置
前言: 本文讲述32位和64位系统中的内存配置,在SQLServer 2005/2008中,DBA们往往尝试开启AWE来限制内存.但是,在SQLServer2012以后,这个选项将被弃用,所以不能使用 ...
- 解决mysql中文乱码(总)
转自:http://hi.baidu.com/cnvienna/blog/item/2e99efdfd94fc61862279801.html MySQL会出现中文乱码的原因不外乎下列几点: .ser ...
- java线程join的意思(转自http://zjj1211.blog_51cto_com)
Join,单词本事就是连接的意思. 先贴出几段代码猜猜结果. <1> public static int Main() { Alpha oAlpha = new Alpha(); Thre ...
- Mac下配置环境变量
1.创建并以 TextEdit 的方式打开 ~/.bash_profile 文件,如果没有则 touch ~/.bash_profile; 然后打开 vim ~/.bash_profile 2.新增环 ...
- php 使用date()函数的报错
错误提示: Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* ...
- 计算机网络——TCP与UDP协议详解
根据应用程序的不同需求,运输层需要两种不同的运输协议,即面向连接的TCP和无连接的UDP. TCP:传输控制协议 TCP特点: 1)TCP是面向连接的运输层协议.所以,应用程序在使用TCP协议之前,必 ...
- socket 基础知识
PHP使用Berkley的socket库来创建它的连接.socket只不过是一个数据结构.你使用这个socket数据结构去开始一个客户端和服务器之间的会话.这个服务器是一直在监听准备产生一个新的会话. ...
- CURL --- 命令行浏览器CURL
CURL --- 命令行浏览器CURL CURL --- 命令行浏览器 CURL? 嗯,说来话长了~~~~ 这东西现在已经是苹果机上内置的命令行工具之一了,可见其魅力之一斑 1)二话不说,先从 ...
- FastJson只序列化java对象的部分属性
public class Student { private int id; private String name; private int age; //get set方法略 } 如下方法: St ...
- hdu 5253 最小生成树
赤裸裸最小生成树,没啥说的,我用kruskal过的 /* * Author : ben */ #include <cstdio> #include <cstdlib> #inc ...