C ++ callback function callback

Source: Internet
Author: User

Methods for implementing callback in C ++

(1) callback Method
The essence of callback is to set a function pointer and call this method when an event needs to be triggered. For example, Windows's window message processing function is of this type. For example, in the following sample code, an event outside the notification must be triggered when download is complete:

typedef void (__stdcall *DownloadCallback)(const char* pURL, bool bOK);void DownloadFile(const char* pURL, DownloadCallback callback){    cout << "downloading: " << pURL << "" << endl;    callback(pURL, true);}void __stdcall OnDownloadFinished(const char* pURL, bool bOK){    cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;}

(2) sink Mode
The essence of sink is that you implement a C ++ interface as required by the other party, and then set your implemented interface to the other party. The other party calls this interface when it needs to trigger an event, the connection point in COM is in this way. If the above requirement for downloading files is implemented using sink, the Code is as follows:

class IDownloadSink{public:    virtual void OnDownloadFinished(const char* pURL, bool bOK) = 0;};class CMyDownloader{public:    CMyDownloader(IDownloadSink* pSink)        :m_pSink(pSink)    {    }    void DownloadFile(const char* pURL)    {        cout << "downloading: " << pURL << "" << endl;        if(m_pSink != NULL)        {            m_pSink->OnDownloadFinished(pURL, true);        }    }private:    IDownloadSink* m_pSink;};class CMyFile: public IDownloadSink{public:    void download()    {        CMyDownloader downloader(this);        downloader.DownloadFile("www.baidu.com");    }    virtual void OnDownloadFinished(const char* pURL, bool bOK)    {        cout << "OnDownloadFinished, URL:" << pURL << "    status:" << bOK << endl;    }};

 

(3) delegate Mode
The essence of delegate is to set the member function pointer to the other party and then let the other party call the function when an event needs to be triggered. C # using delegate to implement event makes C ++ programmers very envious. In C ++, it is still very troublesome to implement delegate because of the language itself. The preceding example is implemented using delegate as follows:

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;    }};

 

We can see that the delegate method has more code than the other two methods above, and we have fixed parameter quantity and type implementation methods above. If you want to implement variable parameters, it is more troublesome. You can refer to the following two methods for variable parameters:

Yet another C #-style delegate class in Standard C ++
Member function pointers and the fastest possible C ++ delegates

 

We can use the following code to test our above implementation:

int _tmain(int argc, _TCHAR* argv[]){    DownloadFile("www.baidu.com", OnDownloadFinished);    CMyFile f1;    f1.download();    CMyFileEx ff;    ff.download();    system("pause");    return 0;}

Finally, we will briefly compare the above three methods for implementing callback:

The first callback method is process-oriented. It is easy to use and flexible, just like the C language itself.
The second method of sink is object-oriented, which is widely used in C ++. It can encapsulate a set of callback interfaces in a sink and is suitable for a series of relatively fixed callback events.
The third method of delegate is also object-oriented. Unlike sink encapsulation, the delegate encapsulation is based on functions, and the granularity is smaller and more flexible than sink.

Which method do you prefer to implement callback?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.