c++回调函数

回调通常发生在两个角色(调用者和实现者),当我们希望发生某个事件时,调用者调用实现者定义的某个函数。如一个Framework提供商,规定了整个程序的框架,当某些事件发生时需要调用某个行为,而这些行为的具体定义是由客户自己来完成的,客户可能根据不同事件选择不同的行为(实现函数运行时的动态调用),因此调用者无法通过具体的函数名进行显示的调用。为了解决这一问题,调用中通过函数指针进行调用,实现者只需将自己定义的函数作为参数传递给调用者即可。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。

关于函数指针,参考:http://www.cnblogs.com/mrlsx/p/5554820.html

函数回调机制:

(1)Callback方式
Callback的本质是设置一个函数指针进去,然后在需要需要触发某个事件时调用该方法, 比如Windows的窗口消息处理函数就是这种类型。

 1 void fun1(int a)
 2 {
 3     cout << a << endl;
 4 }
 5 
 6 void fun2(int a)
 7 {
 8     cout << a*a << endl;
 9 }
10 
11 void caller(void(*f)(int),int a)   //调用者提供接口,具体的实现由客户自己实现
12 {
13     f(a);
14 }
15 
16 int main()
17 {
18     int a;
19     cin >> a;
20     if (a > 0)    //当a>0时,调用fun1
21         caller(fun1, a);
22     else          //当a<=0时,调用fun2
23         caller(fun2, a);
24     return 0;
25 }

 

(2)Sink方式
Sink的本质是你按照对方要求实现一个C++接口,然后把你实现的接口设置给对方,对方需要触发事件时调用该接口, COM中连接点就是居于这种方式。上面下载文件的需求,如果用Sink实现,代码如下:

 1 class IDownloadSink  
 2 {  
 3 public:  
 4     virtual void OnDownloadFinished(const char* pURL, bool bOK) = 0;  
 5 };  
 6   
 7   
 8 class CMyDownloader  
 9 {  
10 public:  
11     CMyDownloader(IDownloadSink* pSink)  
12         :m_pSink(pSink)  
13     {  
14     }  
15   
16     void DownloadFile(const char* pURL)  
17     {  
18         cout << "downloading: " << pURL << "" << endl;  
19         if(m_pSink != NULL)  
20         {  
21             m_pSink->OnDownloadFinished(pURL, true);  
22         }  
23     }  
24   
25 private:  
26     IDownloadSink* m_pSink;  
27 };  
28   
29 class CMyFile: public IDownloadSink  
30 {  
31 public:  
32     void download()  
33     {  
34         CMyDownloader downloader(this);  
35         downloader.DownloadFile("www.baidu.com");  
36     }  
37   
38     virtual void OnDownloadFinished(const char* pURL, bool bOK)  
39     {  
40         cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;  
41     }  
42 };  

(3)Delegate方式
    Delegate的本质是设置成员函数指针给对方,然后让对方在需要触发事件时调用。C#中用Delegate的方式实现Event,让C++程序员很是羡慕,C++中因为语言本身的关系,要实现Delegate还是很麻烦的。上面的例子我们用Delegate的方式实现如下:

  1 class CDownloadDelegateBase  
  2 {  
  3 public:  
  4     virtual void Fire(const char* pURL, bool bOK) = 0;  
  5 };  
  6   
  7 template<typename O, typename T>  
  8 class CDownloadDelegate: public CDownloadDelegateBase  
  9 {  
 10     typedef void (T::*Fun)(const char*, bool);  
 11 public:  
 12     CDownloadDelegate(O* pObj = NULL, Fun pFun = NULL)  
 13         :m_pFun(pFun), m_pObj(pObj)  
 14     {  
 15     }  
 16      
 17     virtual void Fire(const char* pURL, bool bOK)  
 18     {  
 19         if(m_pFun != NULL  
 20             && m_pObj != NULL)  
 21         {  
 22             (m_pObj->*m_pFun)(pURL, bOK);  
 23         }  
 24     }  
 25   
 26 private:  
 27     Fun m_pFun;  
 28     O* m_pObj;  
 29 };  
 30   
 31 template<typename O, typename T>  
 32 CDownloadDelegate<O,T>* MakeDelegate(O* pObject, void (T::*pFun)(const char* pURL, bool))  
 33 {  
 34     return new CDownloadDelegate<O, T>(pObject, pFun);  
 35 }  
 36   
 37 class CDownloadEvent  
 38 {  
 39 public:  
 40     ~CDownloadEvent()  
 41     {  
 42         vector<CDownloadDelegateBase*>::iterator itr = m_arDelegates.begin();  
 43         while (itr != m_arDelegates.end())  
 44         {  
 45             delete *itr;  
 46             ++itr;  
 47         }  
 48         m_arDelegates.clear();  
 49     }  
 50   
 51     void operator += (CDownloadDelegateBase* p)  
 52     {  
 53         m_arDelegates.push_back(p);  
 54     }  
 55   
 56     void operator -= (CDownloadDelegateBase* p)  
 57     {  
 58         ITR itr = remove(m_arDelegates.begin(), m_arDelegates.end(), p);  
 59   
 60         ITR itrTemp = itr;  
 61         while (itrTemp != m_arDelegates.end())  
 62         {  
 63             delete *itr;  
 64             ++itr;  
 65         }  
 66         m_arDelegates.erase(itr, m_arDelegates.end());  
 67     }  
 68   
 69     void operator()(const char* pURL, bool bOK)  
 70     {  
 71         ITR itrTemp = m_arDelegates.begin();  
 72         while (itrTemp != m_arDelegates.end())  
 73         {  
 74             (*itrTemp)->Fire(pURL, bOK);  
 75             ++itrTemp;  
 76         }  
 77     }  
 78   
 79 private:  
 80     vector<CDownloadDelegateBase*> m_arDelegates;  
 81     typedef vector<CDownloadDelegateBase*>::iterator ITR;  
 82 };  
 83   
 84   
 85 class CMyDownloaderEx  
 86 {  
 87 public:  
 88     void DownloadFile(const char* pURL)  
 89     {  
 90         cout << "downloading: " << pURL << "" << endl;  
 91         downloadEvent(pURL, true);  
 92     }  
 93   
 94     CDownloadEvent downloadEvent;  
 95 };  
 96   
 97 class CMyFileEx  
 98 {  
 99 public:  
100     void download()  
101     {  
102         CMyDownloaderEx downloader;  
103         downloader.downloadEvent += MakeDelegate(this, &CMyFileEx::OnDownloadFinished);  
104         downloader.DownloadFile("www.baidu.com");  
105     }  
106   
107     virtual void OnDownloadFinished(const char* pURL, bool bOK)  
108     {  
109         cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;  
110     }  
111 };  
View Code

转自:http://blog.csdn.net/xie1xiao1jun/article/details/8262902

posted on 2016-10-09 16:17  小菜鸡y  阅读(449)  评论(0编辑  收藏  举报