callback pattern
21 Apr 2017
|
|
c回调函数与C++回调类
常用回调方法:
- 第一种Callback的方法是面向过程的,使用简单而且灵活,正如C语言本身。
- 第二种Sink的方法是面向对象的,在C++里使用较多, 可以在一个Sink里封装一组回调接口,适用于一系列比较固定的回调事件。
- 第三种Delegate的方法也是面向对象的,和Sink封装一组接口不同,Delegate的封装是以函数为单位,粒度比Sink更小更灵活。
- signal/slot
C++ 标准中没能提供面向对象的函数指针. 面向对象的函数指针也被称为闭包(closures) 或委托(delegates), 在类似的语言中已经体现出了它的价值.
http://blog.csdn.net/jamesmf/article/details/7710122
http://www.chinaitlab.com/c/special/sjms/Index.html
http://www.cppblog.com/weiym/archive/2012/08/28/188515.html
http://blog.csdn.net/xie1xiao1jun/article/details/8262902
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
typedef void (*DownloadCallback)(const char* pURL, bool bOK);
void DownloadFile(const char* pURL, DownloadCallback callback)
{
cout << "\ncall back.\n" << endl;
cout << "downloading: " << pURL << "" << endl;
callback(pURL, true);
}
void OnDownloadFinished(const char* pURL, bool bOK)
{
cout << "OnDownloadFinished, URL:" << pURL << " status:" << bOK << endl;
}
class SpiSink
{
public:
virtual void OnDownloadFinished(const char* pURL, bool bOK) = 0;
};
class MySpi: public IDownloadSink
{
public:
virtual void OnDownloadFinished(const char* pURL, bool bOK)
{
cout << "OnDownloadFinished, URL:" << pURL << " status:" << bOK << endl;
}
};
class Api
{
public:
Api()
{
cout << "\nsink mode like ctp.\n" << endl;
}
void DownloadFile(const char* pURL)
{
cout << "downloading: " << pURL << "" << endl;
if(m_pSink != NULL)
{
m_pSink->OnDownloadFinished(pURL, true);
}
}
void Registerspi(SpiSink* pSink)
{
m_pSink = pSink;
}
private:
SpiSink* m_pSink;
};
/*
class CDownloadDelegateBase
{
public:
virtual void Fire(const char* pURL, bool bOK) = 0;
};
template<typename O, typename T>
class CDownloadDelegate: public CDownloadDelegateBase
{
typedef void (T::*Fun)(const char*, bool);
public:
CDownloadDelegate(O* pObj = NULL, Fun pFun = NULL)
:m_pFun(pFun), m_pObj(pObj)
{
}
virtual void Fire(const char* pURL, bool bOK)
{
if(m_pFun != NULL
&& m_pObj != NULL)
{
(m_pObj->*m_pFun)(pURL, bOK);
}
}
private:
Fun m_pFun;
O* m_pObj;
};
template<typename O, typename T>
CDownloadDelegate<O,T>* MakeDelegate(O* pObject, void (T::*pFun)(const char* pURL, bool))
{
return new CDownloadDelegate<O, T>(pObject, pFun);
}
class CDownloadEvent
{
public:
~CDownloadEvent()
{
vector<CDownloadDelegateBase*>::iterator itr = m_arDelegates.begin();
while (itr != m_arDelegates.end())
{
delete *itr;
++itr;
}
m_arDelegates.clear();
}
void operator += (CDownloadDelegateBase* p)
{
m_arDelegates.push_back(p);
}
void operator -= (CDownloadDelegateBase* p)
{
ITR itr = remove(m_arDelegates.begin(), m_arDelegates.end(), p);
ITR itrTemp = itr;
while (itrTemp != m_arDelegates.end())
{
delete *itr;
++itr;
}
m_arDelegates.erase(itr, m_arDelegates.end());
}
void operator()(const char* pURL, bool bOK)
{
ITR itrTemp = m_arDelegates.begin();
while (itrTemp != m_arDelegates.end())
{
(*itrTemp)->Fire(pURL, bOK);
++itrTemp;
}
}
private:
vector<CDownloadDelegateBase*> m_arDelegates;
typedef vector<CDownloadDelegateBase*>::iterator ITR;
};
class CMyDownloaderEx
{
public:
void DownloadFile(const char* pURL)
{
cout << "downloading: " << pURL << "" << endl;
downloadEvent(pURL, true);
}
CDownloadEvent downloadEvent;
};
class CMyFileEx
{
public:
void download()
{
CMyDownloaderEx downloader;
downloader.downloadEvent += MakeDelegate(this, &CMyFileEx::OnDownloadFinished);
downloader.DownloadFile("www.baidu.com");
}
virtual void OnDownloadFinished(const char* pURL, bool bOK)
{
cout << "OnDownloadFinished, URL:" << pURL << " status:" << bOK << endl;
}
};
*/
int main(int argc, char* argv[])
{
//callback
DownloadFile("www.baidu.com", OnDownloadFinished);
//sink
CMyFile f1;
f1.download();
//类似ctp的回调方式 sink
Api* api = new Api();
MySpi* spi = new MySpi();
api->Registerspi((SpiSink*)spi);
api->DownloadFile("www.baidu.com");
/*Delegate
CMyFileEx ff;
ff.download();
*/
return 0;
}