1、回调对象中的成员函数,属于回调类的静态成员函数和普通的C函数。CallBackle类中包含一回调函数表callBackList。它用于记录事件名称,指向回调函数及回调对象的指针。该表的每一个节点为一个事件记录EventRecord。每个事件记录包含三个域:事件名指针eventName,指向回调对象的指针pointerToCBO,指向回调函数的指针pointerToCBF或pointerToCBSF(其中,pointerToCBF指向回调对象的成员函数,pointerToCBSF指向回调类的静态成员函数或普通函数。它们同处于一共用体内)。CallBack类所提供的回调机制是这样的:在事件对象上注
2、册回调对象中的回调函数;当事件发生时,事件对象在其回调表中检索并执行回调函数。从而使二者的消息连接得以建立。(关于该类的具体实现,请参阅文后所附的程序清单) 回调对象事件对象事件名 回调对象指针 回调函数指针“event” pointerCBO pointerToCBF或pointerTOCBSF- - - - - -AddCallBack: 注册事件名和指向回调函数,回调对象的指针CallCallBack: 在回调表中,检索注册在指定事件上回调函数并调用它们事件发生时,调用CallCallBack函数对事件event进行处理的成员函数从CallBack类继承的回调表callBackList,
3、 成员函数AddCallBack和CallCallBack。当回调函数为静态成员函数或普通C函数时, pointerToCBO为NULL。事件名是回调表callBackLis中的检索关键字。回调对象中其它成员函数CallBack类的成员函数AddCallBack用来将回调函数注册到事件对象的回调表中。它有两个重载版本:void CallBack:AddCallBack(char *event,CallBackFunction cbf,CallBack *p);AddCallBack(char *event,CallBackStaticFunction cbsf);其中,第一个AddCallBa
4、ck用来将某回调对象的成员函数注册到事件对象的回调表中。第二个AddCallBack用来将或某回调类的静态成员函数注册到事件对象的回调表中。在上参数表中,event是指向事件名字符串的指针,p是指向回调对象的指针,cbf和cbsf分别是指向成员函数及静态成员函数(或普通函数)的指针。当回调函数来自某回调对象SomeObject时,传递成员函数指针应采用如下格式:(CallBackFunction)&SomeObject:MemberFunctionName; 传递SomeObject类的某静态成员函数指针应采用格式:(CallBackStaticFunction)& SomeObject:Fu
5、nctionName;传递程序中普通函数指针时,只需传递函数名即可。CallBack类的成员函数void CallBack:CallCallBack(char *ename, CallData calldata = NULL)用来调用注册在事件ename上的所有回调函数。其中,calldata为数据指针(CallData实际上就是void,详见程序清单)。事件对象可通过它向回调对象传递有用的数据。该成员函数通常在事件对象的成员函数中调用,因为通常只有事件对象的成员函数才能改变对象的内部数据,从而使某些事件发生。成员函数RemoveCallback用来删除注册在事件对象上的回调函数。它的三个重载
6、版本依次为:RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);RemoveCallBack(char *event,CallBackStaticFunction cbsf);RemoveCallBack(char *event);其中,event,cbf,cbsf,p等参数和成员函数AddCallBack中各参数一样。第一个RemoveCallBack用于删除注册在事件event上某回调对象的一个成员函数。第二个RemoveCallBack用于删除注册在事件event上的某普通函数或某回调类的一个静态成员函数。第三个Rem
7、oveCallBack用于删除注册在事件event上的全部回调函数。二、CallBack类的使用方法使用CallBack类,可按以下步骤进行:1确定程序中哪些对象间存在关系,需要建立消息连接。并确定在各特定消息连接关系中,哪个对象是事件对象,哪个对象是回调对象。2事件对象类和回调对象类都必须从CallBack类继承,以获得回调支持。3为事件对象注册回调数据。包括:事件名,回调函数名,指向回调对象的指针。4当你感兴趣的事件发生时,在事件对象类引发事件的成员函数中调用CallCallBack函下面是一个具体的例子。通过它你会对Callback类的使用方法有进一步的了解。/测试程序文件:test.c
8、pp#includecallback.h/“扬声器”类class Speaker:public CallBackprivate:int volume;public:Speaker(int v): volume(v) void IncreaseVolume(int v) /增加音量成员函数volume += v;if(volume 20)/“音量大于20”事件发生了/调用注册在两事件上的回调函数CallCallBack(音量改变了音量大于20, &volume);void DecreaseVolume(int v) /降低音量成员函数volume -= v;if(volume 5) /“音量小于
9、5”事件发生了音量小于5;/“耳朵”类class Ear : public CallBackstatic void Response(CallData callData) /对“音量改变”的反应cout音量改变了.endl;void HighVoiceResponse(CallData callData)/对高音的反应”喂!太吵了!现在音量是:*(int *)callData)void LowVoiceResponse(CallData callData)/ 对低音的反应啊!我听不清了。void main(void)Speaker s(10); /现在音量为10Ear e;/为事件对象s注册回
10、调函数s.AddCallBack(音量大于20”,(CallBackFunction)&Ear:HighVoiceResponse,&e);音量小于5”,(CallBackFunction)&LowVoiceResponse,&,(CallBackStaticFunction)&Response);s.IncreaseVolume(12);/将音量增加12,现在音量位22s.DecreaseVolume(20);/将音量减少20,现在音量位2运行结果:音量改变了.喂!222在上例中,扬声器对象s为事件对象,耳朵对象e为回调对象。s上被注册了三个事件:“音量改变了”,“音量大于20”,“音量小于
11、5”。 回调函数分别为:Response, Ear:HighVoiceResponse,Ear:LowVoiceResponse。当扬声器s通过其成员函数IncreaseVolume和 DecreaseVolume改变音量时,回调对象e会自动作出反应。可见,通过使用CallBack类,在对象间建立消息连接已变为一项很简单和优美的工作。由于笔者水平有限,该类的设计必有不完善之处。如果您对它感兴趣,笔者可与各位C+玩家共同探讨这类问题。联系方式:fei_xiang附:程序清单(本程序在MS VC+5.0和TC+3.0上均编译通过)/回调类的类结构:callback.h#ifndef _CALLBA
12、CK_H#define _CALLBACK_H#includestring.hiostream.h#define CALLBACKLIST_INIT_SIZE 10#define CALLBACKLIST_INCREMENT 5class CallBack;typedef void *CallData;/回调数据指针类型定义typedef void (CallBack:*CallBackFunction)(CallData); /指向回调成员函数的指针typedef void (*CallBackStaticFunction)(CallData); /指向静态成员函数或普通函数的指针类型定义c
13、lass EventRecordchar *eventName; /回调事件名称CallBack *pointerToCBO;/指向回调对象的指针/指向成员函数的指针和指向静态成员函数(或普通函数)指针的共用体unionCallBackFunction pointerToCBF;CallBackStaticFunction pointerToCBSF;EventRecord(void); /事件记录类的缺省构造函数/构造包含成员函数的事件记录EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);/构造包含静态成员函数或普通函
14、数的事件记录EventRecord(char *ename,CallBackStaticFunction pCBSF);EventRecord(void);/析构事件记录void operator = (const EventRecord& er);/重载赋值运算符/判断当前事件记录的事件名是否为enameint operator = (char *ename) const;/判断当前事件记录是否和指定事件记录相等int operator = (const EventRecord& er) const;void Flush(void); /将当前事件记录清空int IsEmpty(void)
15、const;/判断事件记录是否为空(即事件名是否为空)friend class CallBack; /让CallBack类能访问EventRecord的私有成员;class CallBack EventRecord *callBackList; /回调事件表int curpos; /当前事件记录位置int lastpos; /回调表中最后一空闲位置int size; /回调表的大小void MoveFirst(void) curpos = 0; /将当前记录置为第一条记录void MoveNext(void) /将下一条记录置为当前记录if(curpos = lastpos) return;c
16、urpos+;/判断回调表是否被遍历完int EndOfList(void) const return curpos = lastpos; CallBack(void);/构造函数CallBack(const CallBack& cb);/拷贝构造函数CallBack(void);/析构函数void operator = (const CallBack&/ 重载赋值运算符/将回调对象的成员函数、静态成员函数(或普通函数)/注册为事件对象的回调函数void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);void AddCall
17、Back(char *event,CallBackStaticFunction cbsf);/删除注册在指定事件上的回调函数void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);void RemoveCallBack(char *event,CallBackStaticFunction cbsf);void RemoveCallBack(char *event);/ 删除某事件的全部记录/执行注册在某一事件上的所有回调函数void CallCallBack(char *event, CallData calldata
18、 = NULL);#endif/回调类的实现:callback.cpp/EventRecord类的实现EventRecord:EventRecord(void)eventName = NULL;pointerToCBO = NULL;/因为sizeof(CallBackFunction) sizeof(CallBackStaticFunction)pointerToCBF = NULL;EventRecord(char *ename, CallBack *pCBO, CallBackFunction pCBF)pointerToCBO(pCBO), pointerToCBF(pCBF)even
19、tName = strdup(ename);EventRecord(char *ename, CallBackStaticFunction pCBSF)pointerToCBO(NULL), pointerToCBSF(pCBSF)EventRecord(void)if(eventName) delete eventName;void EventRecord:operator = (const EventRecord& er)if(er.eventName)eventName = strdup(er.eventName);elsepointerToCBO = er.pointerToCBO;p
20、ointerToCBF = er.pointerToCBF;int EventRecord:operator = (char *ename) constif(eventName = NULL)|ename = NULL)return eventName = ename;return strcmp(eventName,ename) = 0;operator = (const EventRecord& er) constreturn (er = eventName) /*er和eventname不能交换位置*/&(pointerToCBO = er.pointerToCBO)(pointerToC
21、BO ?(pointerToCBF = er.pointerToCBF):(pointerToCBSF = er.pointerToCBSF);Flush(void)if(eventName)delete eventName;IsEmpty(void) constif(eventName = NULL)return 1;return 0;/Callback类的实现CallBack:CallBack(void)/按初始尺寸为回调表分配内存空间callBackList = new EventRecordCALLBACKLIST_INIT_SIZE;if(!callBackList)cerr mem
22、ory allocation error.exit(1);size = CALLBACKLIST_INIT_SIZE;lastpos = 0;curpos = 0; cb): curpos(cb.curpos),lastpos(cb.lastpos),size(cb.size)callBackList = new EventRecordsize;/一一复制各条事件记录for(int i = 0; i size; i+) callBackListi = cb.callBackListi;operator = (const CallBack& cb)curpos = cb.curpos;lastp
23、os = cb.lastpos;size = cb.size;delete callBackList;/删除旧的回调表/重新分配内存空间CallBack(void)AddCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)/如事件名为空,退出if( (event = NULL)?1:(strlen(event) = 0) return;/寻找因删除事件记录而产生的第一个空闲位置,并填写新事件记录for(int start=0;startlastpos;start+)if(callBackListstart.IsEmpty()c
24、allBackListstart = EventRecord(event,pCBO,pCBF);break;if(start lastpos) return; /确实存在空闲位置/没有空闲位置,在回调表后追加新记录if(lastpos = size) /回调表已满,需“伸长”EventRecord *tempList = callBackList;/暂存旧回调表指针/以一定的步长“伸长”回调表callBackList = new EventRecordsize + CALLBACKLIST_INCREMENT;/复制旧回调表中的记录 i+) callBackListi = tempListi;delete tempList;/删除旧回调表size += CALLBACKLIST_INCREMENT;/记下新回调表的尺寸/构造新的事件记录并将其填入回调表中callBac
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1