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篇)
回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定 ...
随机推荐
- LA 3516 Exploring Pyramids (记忆化搜索)
题意 给定一个DFS序列,问能有多少树与之对应. 思路 设输入序列为S,dp(i, j)为子序列Si, Si+1, --, Sj对应的树的个数,则边界条件为d(i, i) = 1,且Si != Sj时 ...
- C# list installed softwares
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Product&q ...
- Ref相关的名词解释
NV (NOT-VOLATILE),即非易失性,断电不会丢失的存储信息,包括生产信息.客户信息.产品信息等等. 它们都保存在不同(FLASH)分区,并根据不同的分区提供不同的接口.数据结构和管理机制. ...
- C与C++的区别无随时更新
C没有calss类,只有结构体struct class A; 在C中这样写就是错误的,C没有关键字class C的字符指针不会自动开辟内存空间,必须对这个指针指向的地址手动开辟空间后才可以写入数据. ...
- js获取当前url信息
window.location 属性 描述 hash 设置或获取 href 属性中在井号"#"后面的分段. host 设置或获取 location 或 URL 的 hostname ...
- Oracle buffer cache与相关的latch等待事件
buffer cache与相关的latch等待事件 1.buffer cache 2.latch:cache buffers lru chain 3.latch:cache buffers chain ...
- Windows 8 电话激活密钥。(更新至 2013-07-21)
MAK密钥,可用于电话激活专业版&企业版,2013.7.21 更新,共22枚: slmgr.vbs -ipk MQJNQ-G2TKM-YJP7W-CCXVY-VQR92slmgr.vbs -i ...
- 【转】Xcode中的iOS模拟器(iOS Simulator)的介绍和使用心得
iOS模拟器简介 iOS功能简介 iOS模拟器,是在Mac下面开发程序时,开发iOS平台的程序时候,可以使用的辅助工具. 其功能是,帮你模拟iOS平台设备,在模拟器上运行对应的程序,以方便你没有实体设 ...
- Informatica9.6.1在Linux Red Hat 5.8上安装遇到的有关问题整理_3
3.Repository Service启动后的页面编码问题 1)错误信息: 2)原因分析及解决步骤 原因分析: informatica产品安装背后AdminConsole的Code page默认为U ...
- mysql优化SQL语句的一般步骤及常用方法
一.优化SQL语句的一般步骤 1. 通过show status命令了解各种SQL的执行频率 mysqladmin extended-status 或: show [session|global]sta ...