首页 > 代码库 > c++回调函数

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时,调用fun121         caller(fun1, a);22     else          //当a<=0时,调用fun223         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

c++回调函数