函数指针和回调函数
2016-05-28 11:02
155 查看
C++很多类库都用回调函数,比如MFC中的定时器,消息机制,hook机制等。回调函数与QT中的信号-槽机制很像,但回调更快,而信号-槽更灵活。
1. 回调函数
什么是回调函数呢?回调函数其实就是一个通过函数指针调用的函数!假如你把A函数的指针当作参数传给B函数,然后在B函数中通过A函数传进来的这个指针调用A函数,那么这就是回调机制。A函数就是回调函数,而通常情况下,A函数是系统在符合你设定条件的情况下会自动执行,比如Windows下的消息触发等等。那么调用者和被调用者的关系就被拉开了,就像是中断处理函数那样。
更为通俗的定义理解:
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。
2. 函数指针
函数指针是一个指针,只是这个指针它不像普通的指针指向是是一个变量,此时它指向的是一个函数,也就是它存储的是一个函数的地址,如果我们愿意的话,可以改变这个它的值,让他由指向funA转变为指向funB,那么这个函数指针的作用就改变了。
3. 函数指针的使用
函数指针的声明:
4. 回调函数的使用
回调函数的使用其实和上面函数指针示例是很一致的,只是上面的实例中pFun是我们自己调用的。现在我们在MFC中让系统调用一下吧。
先看一下SetTimer函数声明:
其中lpfnTimer是这么解释的:Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application's message
queue and handled by the CWnd object.
也就是或如果为NULL的话,系统自动触发WM_Timer消息,然后调用OnTimer函数。
我们调用自己的自定义回调函数。
我们还注意到回调函数用CALLBACK修饰,我们可以在windef.h中发现:
1. 回调函数
什么是回调函数呢?回调函数其实就是一个通过函数指针调用的函数!假如你把A函数的指针当作参数传给B函数,然后在B函数中通过A函数传进来的这个指针调用A函数,那么这就是回调机制。A函数就是回调函数,而通常情况下,A函数是系统在符合你设定条件的情况下会自动执行,比如Windows下的消息触发等等。那么调用者和被调用者的关系就被拉开了,就像是中断处理函数那样。
更为通俗的定义理解:
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。
2. 函数指针
函数指针是一个指针,只是这个指针它不像普通的指针指向是是一个变量,此时它指向的是一个函数,也就是它存储的是一个函数的地址,如果我们愿意的话,可以改变这个它的值,让他由指向funA转变为指向funB,那么这个函数指针的作用就改变了。
3. 函数指针的使用
函数指针的声明:
typedef 返回类型(*函数指针类型名)(函参列表);示例:
typedef void(*Fun)(int,int); //定义函数指针类型 void min(int a,int b); void max(int a,int b); void min(int a,int b) { int minvalue=a<b?a:b; std::cout<<"min value is "<<minvalue<<"\n"; } void max(int a,int b) { int maxvalue=a>b?a:b; std::cout<<"Max value is "<<maxvalue<<"\n"; } int _tmain(int argc, _TCHAR* argv[]) { Fun pFun=NULL; //定义函数指针变量pFun //pFun=min;//两种赋值方式都支持 pFun=&min; pFun(1,2);//这里获得最小值 //pFun=max; pFun=&max; pFun(1,2);//这里获得最大值 return 0; }
4. 回调函数的使用
回调函数的使用其实和上面函数指针示例是很一致的,只是上面的实例中pFun是我们自己调用的。现在我们在MFC中让系统调用一下吧。
先看一下SetTimer函数声明:
UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );
其中lpfnTimer是这么解释的:Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application's message
queue and handled by the CWnd object.
也就是或如果为NULL的话,系统自动触发WM_Timer消息,然后调用OnTimer函数。
我们调用自己的自定义回调函数。
CALLBACK VOID callback_fun(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { TRACE("CallBack\n");//debug下运行控制台输出CallBack } void CTestCallBackDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 SetTimer(1,1000,(TIMERPROC)callback_fun);//每一秒回调一次 }另外,需要注意的是回调函数必须是全局函数或者静态成员函数,因为普通的成员函数会隐含着一个传递函数作为参数,也就是this指针。因此如果使用普通成员函数作为回调函数的话会导致函数参数个数不匹配,因此编译失败。这也是线程函数是多为静态函数的原因。
我们还注意到回调函数用CALLBACK修饰,我们可以在windef.h中发现:
#define CALLBACK __stdcall
相关文章推荐
- 【NOIP2010】关押罪犯
- 漂亮回答面试官struts2的原理
- 详细记录python的range()函数用法
- 肿瘤检测
- 《CSS权威指南》学习记录——特殊性和层叠
- Ehcache Memcache Redis 初步 (一)
- 分页关键知识点总结
- RN----导入组件,import from 'xxxx'的用法详解
- hdu 2639Bone Collector II(01背包求第k大)
- Android应用签名与防止反编译(一)
- 多视图的参数传递
- Android时间平移以及计算时间差,以及计算工作日
- Android Bander设计与实现 - 设计篇
- I2C总线原理及应用实例
- Java中“引用”的几种类型
- Apache与Nginx的区别
- [leetcode] 【数组】 89. Gray Code
- 性能调优概述,你不能不知的优化策略
- C++的性能优化实践 map hash_map unodered_map性能
- jmeter 建立一个扩展LDAP测试计划