一直對回調機制不是很了解,今天索性搜了很多資料順便整理一下,進步一點點。
1.Callback方式(回調函數)
什么是回調函數?
簡而言之,回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用為調用它所指向的函數時,我們就說這是回調函數。
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; } //初始化
DownloadCallback = OnDownloadFinished;
回調函數是繼續自C語言的,因而,在C++中,應只在與C代碼建立接口,或與已有的回調接口打交道時,才使用回調函數。除了上述情況,在C++中應使用虛擬方法
2.虛擬方法
本質是你按照對方要求實現一個C++接口,然后把你實現的接口設置給對方,對方需要觸發事件時調用該接口
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.sina.com"); } virtual void OnDownloadFinished(const char* pURL, bool bOK) { cout << "OnDownloadFinished, URL:" << pURL << " status:" << bOK << endl; } };
這里使用多態,子類指針實例化父類指針。
父類子類指針函數調用注意事項
1,如果以一個基礎類指針指向一個衍生類對象(派生類對象),那么經由該指針只能訪問基礎類定義的函數(靜態聯翩)
2,如果以一個衍生類指針指向一個基礎類對象,必須先做強制轉型動作(explicit cast),這種做法很危險,也不符合生活習慣,在程序設計上也會給程序員帶來困擾。(一般不會這么去定義)
3,如果基礎類和衍生類定義了相同名稱的成員函數,那么通過對象指針調用成員函數時,到底調用那個函數要根據指針的原型來確定,而不是根據指針實際指向的對象類型確定。