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 };
转自:http://blog.csdn.net/xie1xiao1jun/article/details/8262902