*C++中的回調

來源:互聯網
上載者:User
對於回呼函數的編寫始終是寫特殊處理功能程式時用到的技巧之一。先介紹一下回調的使用基本方法與原理。

  1、在這裡設:回呼函數為A()(這是最簡單的情況,不帶參數,但我們應用的實際情況常常很會複雜),使用回呼函數的操作函數為B(), 但B函數是需要參數的,這個參數就是指向函數A的地址變數,這個變數一般就是函數指標。使用方法為:

int A(char *p); // 回呼函數
typedef int(*CallBack)(char *p) ; // 聲明CallBack 類型的函數指標
CallBack myCallBack ; // 聲明函數指標變數
myCallBack = A; // 得到了函數A的地址

  B函數一般會寫為 B(CallBack lpCall,char * P,........); // 此處省略了p後的參數形式 。

  所以回調機制可解為,函數B要完成一定功能,但他自己是無法實現全部功能的。 需要藉助於函數A來完成,也就是回呼函數。B的實現為:

B(CallBack lpCall,char *pProvide)
{
 ........... // B 的自己實現功能語句
 lpCall(PpProvide); // 藉助回調完成的功能 ,也就是A函數來處理的。
 ........... // B 的自己實現功能語句
}
// -------------- 使用例子 -------------
char *p = "hello!";
CallBack myCallBack ;
myCallBack = A ;
B(A, p);

  以上就是回調的基本應用,本文所說的變身,其實是利用傳入不同的函數地址,實現調用者類與回呼函數所在類的不同轉換。

  1、問題描述

  CUploadFile 類完成資料上傳,與相應的介面進度顯示。

  主要函數Send(...) 和回呼函數 GetCurState() ;

class CUploadFile : public CDialog
{
 ......
 int Send(LPCTSTR lpServerIP, LPCTSTR lpServerPort, LPCTSTR UploadFilePath) ;
 static int GetCurState(int nCurDone, int nInAll, void * pParam) ;
 ......
}
int CUploadFile ::Send(LPCTSTR lpServerIP, LPCTSTR lpServerPort, LPCTSTR UploadFilePath)
{
 ... // 匯出傳輸資料的函數
 int ret = Upload( (LPSTR)(LPCTSTR)m_strData,
    GetCurState, // 在這個回呼函數中處理介面
    this, // CUploadFile 的自身指標 ,也就是pParam 所接受的參數
    (LPSTR)(LPCTSTR)UploadFilePath,
    "",
    "",
 );
}
int CUploadFile ::GetCurState(int nCurData, int nInAll, void * pParam)
{
 .........
 UploadFile *pThis = (UploadFile *)pParam; // nCurData 當前以傳出的資料量
 // nInAll 總的資料量
 // 有了pThis可以對介面進行各種操作了。
 .............
}

  但大家仔細觀察就可以發現,這個類把資料傳送和介面顯示聚和到了一起,不容易得到複用。而且在複用過程中需要改動較多的地方 。

  請大家記住現在的回呼函數傳入的類本身的靜態成員函數。

  現在我們把資料的傳送和介面的顯示分離。回調則要傳入的是介面處理類的靜態函數。

  介面處理類 CShowGUI,資料上傳類 CUploadData

class CUploadData
{
 ......
 typedef int(*SetUploadCaller)(int nCurData, int nInAll, void * pParam);
 int UploadFile(LPCTSTR lpFileNamePath,LPVOID lparam,SetUploadCaller Caller );
 // 接受外界出入的參數,主要是回呼函數的地址通過參數Caller,
 int Send(LPCTSTR lpServerIP, LPCTSTR lpServerPort, LPCTSTR UploadFilePath) ;
 ...... // 注意此時不在需要GetCurState 函數了 。
}

class CShowGUI: public CDialog
{
 .......
 typedef int(*SetUploadCaller)(int nCurData, int nInAll, void * pParam);
 void SetCallBack(LPCTSTR strPath);
 static int GetCurState(int nCurData, int nInAll, void * pParam) ;
 CUploadData m_Uploa
 d ; // 資料上傳類是介面顯示類的一個成員變數。
 .......
}

void CShowGUI :: SetCallBack(LPCTSTR strPath)
{
 CUploadData myUploadData ;
 SetUploadCaller myCaller; // 聲明一個函數指標變數
 myCaller = CurState ; // 取得介面處理函數的地址
 myUploadData .UploadFile(strPath,this,myCaller); // 介面處理類的函數傳入,實現了資料傳入與介面處理的分離 .
}

  通過上面的示範做到了介面與資料的分離,回呼函數分別扮演了不同角色,所以隨著處理問題的不同應靈活應用,但同樣因為處理資料類不知道介面處理類或外部調用類的類型,而更無法靈活地處理介面的不同顯示方式。這方面還希望喜歡鑽研技術的朋友繼續研究。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.