现在的位置: 首页 > 综合 > 正文

函数指针和回调函数

2018年06月08日 ⁄ 综合 ⁄ 共 2047字 ⁄ 字号 评论关闭

C++很多类库都喜欢用回调函数,MFC中的定时器,消息机制,hook机制等待,包括现在在研究的cocos2d-x中也有很多的回调函数。


1.回调函数

什么是回调函数呢?回调函数其实就是一个通过函数指针调用的函数!假如你把A函数的指针当作参数传给B函数,然后在B函数中通过A函数传进来的这个指针调用A函数,那么这就是回调机制。B函数就是回调函数,而通常情况下,A函数是系统在符合你设定条件的情况下会自动执行,比如Windows下的消息触发等等。那么调用者和被调用者的关系就被拉开了,就像是中断处理函数那样。


2.函数指针

函数指针是一个指针,只是这个指针它不像普通的指针指向是是一个变量,此时它指向的是一个函数,也就是它存储的是一个函数的地址,如果我们愿意的话,可以改变这个它的值,让他由指向funA转变为指向funB,那么这个函数指针的作用就改变了。


3.函数指针的使用


3.1函数指针声明

  1. typedef 返回类型(*函数指针类型名)(函参列表);  


3.2示例

  1. typedef void(*Fun)(int,int); //定义函数指针类型  
  2. void min(int a,int b);  
  3. void max(int a,int b);  
  4.   
  5. void min(int a,int b)  
  6. {  
  7.     int minvalue=a<b?a:b;  
  8.     std::cout<<"min value is "<<minvalue<<"\n";  
  9. }  
  10.   
  11. void max(int a,int b)  
  12. {  
  13.     int maxvalue=a>b?a:b;  
  14.     std::cout<<"Max value is "<<maxvalue<<"\n";  
  15. }  
  16.   
  17. int _tmain(int argc, _TCHAR* argv[])  
  18. {  
  19.     Fun pFun=NULL; //定义函数指针变量pFun  
  20.     //pFun=min;//两种赋值方式都支持  
  21.     pFun=&min;  
  22.     pFun(1,2);//这里获得最小值  
  23.     //pFun=max;  
  24.     pFun=&max;  
  25.     pFun(1,2);//这里获得最大值  
  26.     return 0;  
  27. }  

我想这么写应该是很一目了然了。


4.回调函数的使用

回调函数的使用其实和上面函数指针示例是很一致的,只是上面的实例中pFun是我们自己调用的。现在我们在MFC中让系统调用一下吧。


先看一下SetTimer函数声明:

  1. UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWNDUINTUINTDWORD) );  

其中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函数。


我们调用自己的自定义回调函数。

  1. CALLBACK VOID callback_fun(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)  
  2. {  
  3.     TRACE("CallBack\n");//debug下运行控制台输出CallBack  
  4. }  
  5.   
  6. void CTestCallBackDlg::OnBnClickedButton1()  
  7. {  
  8.     // TODO: 在此添加控件通知处理程序代码  
  9.     SetTimer(1,1000,(TIMERPROC)callback_fun);//每一秒回调一次  
  10. }  

另外,需要注意的是回调函数必须是全局函数或者静态成员函数,因为普通的成员函数会隐含着一个传递函数作为参数,也就是this指针。因此如果使用普通成员函数作为回调函数的话会导致函数参数个数不匹配,因此编译失败。这也是线程函数是多为静态函数的原因。

我们还注意到回调函数用CALLBACK修饰,我们可以在windef.h中发现:

  1. #define CALLBACK    __stdcall  

CALLBACK其实就是__stdcall,还记得上篇讲过的函数调用约定吗?

抱歉!评论已关闭.