zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Windows 7 Phone 文档数据库Rapid Repository正式发布
    Adobe展示HTML5动画制作IDE
    详解Android实现全屏正确方法
    qtform.com计划
    Adobe加速布局移动开发:Flash Builder+Flex+AIR+Catalyst
    预览:Visual Basic与C#中的异步语法
    Windows 7主题中的壁纸从哪里来?
    F#的编译器及标准库使用Apache 2.0协议开源(暂时还没有看到未来)
    开发者谈Symbian、iPhone、Android、MeeGo平台
    MeeGo 1.1发布
  • 原文地址:https://www.cnblogs.com/mrlsx/p/5942719.html
Copyright © 2011-2022 走看看