青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

(1)Callback方式
Callback的本質是設置一個函數指針進去,然后在需要需要觸發某個事件時調用該方法, 比如Windows的窗口消息處理函數就是這種類型。

比如下面的示例代碼,我們在Download完成時需要觸發一個通知外面的事件:
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方式
Sink的本質是你按照對方要求實現一個C++接口,然后把你實現的接口設置給對方,對方需要觸發事件時調用該接口, COM中連接點就是居于這種方式。

上面下載文件的需求,如果用Sink實現,代碼如下:
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方式
Delegate的本質是設置成員函數指針給對方,然后讓對方在需要觸發事件時調用。
C#中用Delegate的方式實現Event,讓C++程序員很是羨慕,C++中因為語言本身的關系,要實現Delegate還是很麻煩的。
上面的例子我們用Delegate的方式實現如下: 
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;
    }
};

可以看到Delegate的方式代碼量比上面其他2種方式大多了,并且我們上面是固定參數數量和類型的實現方式,如果要實現可變參數,要更加麻煩的多。
可變參數的方式可以參考這2種實現:
Yet Another C#-style Delegate Class in Standard C++
Member Function Pointers and the Fastest Possible C++ Delegates


我們可以用下面的代碼測試我們上面的實現:
int _tmain(int argc, _TCHAR* argv[])
{

    DownloadFile("www.baidu.com", OnDownloadFinished);

    CMyFile f1;
    f1.download();

    CMyFileEx ff;
    ff.download();

    system("pause");

    return 0;
}


最后簡單比較下上面3種實現回調的方法:
第一種Callback的方法是面向過程的,使用簡單而且靈活,正如C語言本身。
第二種Sink的方法是面向對象的,在C++里使用較多, 可以在一個Sink里封裝一組回調接口,適用于一系列比較固定的回調事件。
第三種Delegate的方法也是面向對象的,和Sink封裝一組接口不同,Delegate的封裝是以函數為單位,粒度比Sink更小更靈活。 

你更傾向于用哪種方式來實現回調?
posted on 2012-08-28 12:36 Richard Wei 閱讀(5041) 評論(3)  編輯 收藏 引用 所屬分類: C++

FeedBack:
# re: C++中實現回調機制的幾種方式
2012-08-28 17:43 | Richard Wei
借助C++11種的function, 可以讓我們無差別的對待普通函數和類成員函數,實現delegate會容易很多  回復  更多評論
  
# re: C++中實現回調機制的幾種方式
2012-08-30 16:54 | 畢達哥拉斯半圓
@Richard Wei
這個好呀!  回復  更多評論
  
# re: C++中實現回調機制的幾種方式
2012-08-30 16:54 | 畢達哥拉斯半圓
收藏了,學習一下!  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美美女操人视频| 午夜精品短视频| 久久综合九色欧美综合狠狠| 欧美亚洲一区二区在线| 美日韩精品视频| 亚洲精品一二三区| 久久av在线看| 国产日韩视频| 在线视频日韩| 久久久久在线| 性娇小13――14欧美| 欧美伦理影院| 日韩亚洲一区在线播放| 亚洲人成毛片在线播放| 亚洲欧洲av一区二区| 欧美日韩亚洲精品内裤| 亚洲欧洲日本国产| 91久久精品一区| 欧美成人免费va影院高清| 亚洲第一精品影视| 欧美ed2k| 欧美日韩精品综合| 亚洲欧美怡红院| 久久精品国产第一区二区三区| 亚洲视频碰碰| 欧美一级午夜免费电影| 亚洲精品男同| 欧美成人黄色小视频| 久久中文字幕导航| 国产精品久久久久久久久久妞妞| 欧美精品亚洲| 亚洲国产精品一区二区第一页| 牛牛影视久久网| 国产欧美视频在线观看| 妖精视频成人观看www| 亚洲大片av| 欧美日韩另类一区| 久久久精品国产99久久精品芒果| 亚洲欧洲精品天堂一级| 一区二区三区亚洲| 久久国产精品亚洲va麻豆| 亚洲国产精品成人| 91久久久久久国产精品| 亚洲无毛电影| 久久精品国产久精国产思思 | 美国十次成人| 久久久精品一区二区三区| 国产精品网红福利| 99亚洲伊人久久精品影院红桃| 欧美老女人xx| 亚洲国产高清在线观看视频| 一本色道精品久久一区二区三区| 国产午夜精品全部视频播放| 亚洲天堂成人在线视频| 亚洲一区中文| 亚洲一区中文| 亚洲国产成人精品久久久国产成人一区 | 欧美国产亚洲精品久久久8v| 亚洲图片激情小说| 亚洲小视频在线| 一本久久知道综合久久| 欧美一区在线看| 国产精品永久免费观看| 欧美日韩国产高清| 久久―日本道色综合久久| 亚洲欧美国产高清va在线播| 亚洲美女诱惑| 在线亚洲国产精品网站| 欧美a级片一区| 亚洲人成网站999久久久综合| 亚洲激情图片小说视频| 亚洲三级免费观看| 亚洲片在线观看| 亚洲激情视频在线观看| 午夜久久tv| 亚洲激情一区二区| 亚洲欧美日本在线| 欧美一级在线播放| 欧美成人中文字幕| 亚洲国产婷婷| 亚洲黄色毛片| 亚洲专区在线| 国产精品人成在线观看免费| 国产精品美女主播| 精品91久久久久| 亚洲香蕉在线观看| 欧美mv日韩mv国产网站app| 亚洲图片在区色| 久久综合一区二区三区| 欧美日本亚洲韩国国产| av72成人在线| 欧美1级日本1级| 亚洲一区二区成人在线观看| 国产精品久久久久天堂| 午夜亚洲福利在线老司机| 亚洲国产精品精华液网站| 久久久久久网| 一区二区三区久久网| 在线亚洲欧美专区二区| 欧美色一级片| 亚洲电影免费在线观看| 欧美va亚洲va香蕉在线| 亚洲在线观看免费| 老**午夜毛片一区二区三区| 亚洲欧洲av一区二区| 一区二区三区在线观看视频| 日韩写真视频在线观看| 久久福利电影| 精品1区2区| 欧美va天堂va视频va在线| 亚洲色在线视频| 美女日韩在线中文字幕| **网站欧美大片在线观看| 欧美大片一区二区三区| 国产美女搞久久| 久久精品欧美| 欧美中文字幕在线| 一本大道久久a久久精二百| 一区二区三欧美| 欧美日韩成人一区二区| 美女性感视频久久久| 久久视频一区二区| 欧美在线视频一区二区三区| 久久综合伊人77777| 久久免费高清视频| 欧美日韩一区二区三区免费看| 亚洲第一毛片| 99精品99久久久久久宅男| 99视频精品在线| 国内久久精品视频| av不卡免费看| 亚洲精品乱码久久久久久按摩观| 亚洲国产高清aⅴ视频| 国产精品久久久久久久第一福利| 先锋影音国产精品| 国产夜色精品一区二区av| 久久精品中文字幕一区| 亚洲你懂的在线视频| 久久综合九色九九| 欧美性大战久久久久久久蜜臀| 亚洲欧美乱综合| 久久综合给合久久狠狠色| 亚洲一区成人| 欧美日韩直播| 欧美亚洲一区| 亚洲第一偷拍| 一区二区三区 在线观看视频 | 亚洲专区一区二区三区| 永久久久久久| 亚洲人成网站在线播| 欧美午夜宅男影院| 欧美国产精品中文字幕| 亚洲精品国产系列| 欧美亚洲日本国产| 亚洲成色精品| 欧美极品影院| 欧美高清视频免费观看| 亚洲午夜一区二区| 亚洲女优在线| 国产精品99久久久久久久女警 | 国产午夜精品视频免费不卡69堂| 亚洲激情在线观看视频免费| 亚洲国产视频直播| 激情六月综合| 亚洲国产精品成人综合色在线婷婷| 欧美成人免费在线| 久久天天狠狠| 一区二区三区四区蜜桃| 欧美激情网友自拍| 久久综合九色综合久99| 久久精品2019中文字幕| 香蕉久久夜色精品国产| 亚洲黄色影院| 日韩亚洲欧美在线观看| 激情成人综合网| 国产精品视频一二三| 老牛影视一区二区三区| 久久人人97超碰精品888| 亚洲影视在线| 欧美激情一区在线| 久久久久久穴| 亚洲免费网址| 国产日韩一区二区三区在线| 99精品久久久| 欧美日韩亚洲一区二区三区四区| 欧美久久综合| 国产精品午夜av在线| 国产精品久99| 国产色综合久久| 亚洲丁香婷深爱综合| 日韩一本二本av| 久久中文字幕一区| 久久久国产午夜精品| 欧美日韩国产一级| 国产一区二区三区四区老人| 加勒比av一区二区| 亚洲最新视频在线| 蜜臀av性久久久久蜜臀aⅴ四虎| 亚洲私人黄色宅男| 欧美日韩国产另类不卡|