用過C++進行過面向對象程序設計的用戶都知道,程序中的對象很少單獨存在。不考慮對象間的相互作用幾乎是不可能的。所以,標識對象間的關系或建立對象間的消息連接是面向對象程序設計的一項重要任務。本文著重從C++程序設計的角度,提出一種建立對象間消息連接的實用方法。如果你想詳細了解面向對象程序設計技術,請參閱有關專著。
大家都知道對象是數據和方法的封裝體。在C++中,它們分別表現為數據成員和成員函數。程序設計者通過執行對象的各種方法,來改變對象的狀態(即改變對象的屬性數據)。從而使該對象發生某些“事件”。當一對象發生某事件時,它通常需向其它相關對象發送“消息”,請求它們作出一些處理。 這時,發生事件並向其它對象請求處理的對象被稱為“事件對象”,而處理事件的對象被稱為“回調對象”。回調對象對事件的處理稱為“回調函數”。在C++中,這一過程相當於:當事件對象發生事件時,調用回調對象的某些成員函數。通常的作法是回調對象向事件對象傳遞對象指針。但這種方法不通用。為了減少程序設計的工作量,本文提出一種建立對象間消息連接的系統方法。它的思路是:將“事件發生→請求處理→執行處理”這一過程抽象成一個“回調”(CallBack)類。通過繼承,用戶可以輕松獲取建立對象間消息連接的機制。
一、回調類的數據結構及其成員函數
本文提出的CallBack類支持三種回調函數。它們是:回調對象中的成員函數,屬於回調類的靜態成員函數和普通的C函數。CallBackle類中包含一回調函數表callBackList。它用於記錄事件名稱,指向回調函數及回調對象的指針。該表的每一個節點為一個事件記錄EventRecord。每個事件記錄包含三個域:事件名指針eventName,指向回調對象的指針pointerToCBO,指向回調函數的指針pointerToCBF或pointerToCBSF(其中,pointerToCBF指向回調對象的成員函數,pointerToCBSF指向回調類的靜態成員函數或普通函數。它們同處於一共用體內)。CallBack類所提供的回調機制是這樣的:在事件對象上注冊回調對象中的回調函數;當事件發生時,事件對象在其回調表中檢索並執行回調函數。從而使二者的消息連接得以建立。(關於該類的具體實現,請參閱文後所附的程序清單)
事件名 回調對象指針 回調函數指針 “event” pointerCBO pointerToCBF或pointerTOCBSFAddCallBack: 注冊事件名和指向回調函數,回調對象的指針
CallCallBack: 在回調表中,檢索注冊在指定事件上回調函數並調用它們
事件發生時,調用CallCallBack函數
對事件event進行處理的成員函數
從CallBack類繼承的回調表callBackList, 成員函數AddCallBack和CallCallBack。
當回調函數為靜態成員函數或普通C函數時, pointerToCBO為NULL。
事件名是回調表callBackLis中的檢索關鍵字。
回調對象中其它成員函數
CallBack類的成員函數AddCallBack用來將回調函數注冊到事件對象的回調表中。它有兩個重載版本:
- void CallBack::AddCallBack(char *event,CallBackFunction cbf,CallBack *p);
- void CallBack::AddCallBack(char *event,CallBackStaticFunction cbsf);
其中,第一個AddCallBack用來將某回調對象的成員函數注冊到事件對象的回調表中。第二個AddCallBack用來將或某回調類的靜態成員函數注冊到事件對象的回調表中。在上參數表中,event是指向事件名字符串的指針,p是指向回調對象的指針,cbf和cbsf分別是指向成員函數及靜態成員函數(或普通函數)的指針。當回調函數來自某回調對象SomeObject時,傳遞成員函數指針應采用如下格式:(CallBackFunction)&SomeObject::MemberFunctionName; 傳遞SomeObject類的某靜態成員函數指針應采用格式:(CallBackStaticFunction)& SomeObject::FunctionName;傳遞程序中普通函數指針時,只需傳遞函數名即可。
CallBack類的成員函數void CallBack::CallCallBack(char *ename, CallData calldata = NULL)用來調用注冊在事件ename上的所有回調函數。其中,calldata為數據指針(CallData實際上就是void*,詳見程序清單)。事件對象可通過它向回調對象傳遞有用的數據。該成員函數通常在事件對象的成員函數中調用,因為通常只有事件對象的成員函數才能改變對象的內部數據,從而使某些事件發生。
成員函數RemoveCallback用來刪除注冊在事件對象上的回調函數。它的三個重載版本依次為:
- void CallBack::RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);
- void CallBack::RemoveCallBack(char *event,CallBackStaticFunction cbsf);
- void CallBack::RemoveCallBack(char *event);
其中,event,cbf,cbsf,p等參數和成員函數AddCallBack中各參數一樣。第一個RemoveCallBack用於刪除注冊在事件event上某回調對象的一個成員函數。第二個RemoveCallBack用於刪除注冊在事件event上的某普通函數或某回調類的一個靜態成員函數。第三個RemoveCallBack用於刪除注冊在事件event上的全部回調函數。