回调函数在C++的应用文档格式.docx
《回调函数在C++的应用文档格式.docx》由会员分享,可在线阅读,更多相关《回调函数在C++的应用文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
回调对象中的成员函数,属
于回调类的静态成员函数和普通的C函数。
CallBackle类中包含一回调函数表callBackL
ist。
它用于记录事件名称,指向回调函数及回调对象的指针。
该表的每一个节点为一个
事件记录EventRecord。
每个事件记录包含三个域:
事件名指针eventName,指向回调对
象的指针pointerToCBO,指向回调函数的指针pointerToCBF或pointerToCBSF(其中,po
interToCBF指向回调对象的成员函数,pointerToCBSF指向回调类的静态成员函数或普通
函数。
它们同处于一共用体内)。
CallBack类所提供的回调机制是这样的:
在事件对象上
注册回调对象中的回调函数;
当事件发生时,事件对象在其回调表中检索并执行回调函
数。
从而使二者的消息连接得以建立。
(关于该类的具体实现,请参阅文后所附的程序
清单)回调对象
事件对象
事件名回调对象指针回调函数指针
“event”pointerCBOpointerToCBF或
pointerTOCBSF
------
AddCallBack:
注册事件名和指向回调函数,回调对象的指针
CallCallBack:
在回调表中,检索注册在指定事件上回调函数并调用它们
事件发生时,调用CallCallBack函数
对事件event进行处理的成员函数
从CallBack类继承的回调表callBackList,成员函数AddCallBack和CallCallBack。
当回调函数为静态成员函数或普通C函数时,pointerToCBO为NULL。
事件名是回调表callBackLis中的检索关键字。
回调对象中其它成员函数
CallBack类的成员函数AddCallBack用来将回调函数注册到事件对象的回调表中。
它有
两个重载版本:
voidCallBack:
:
AddCallBack(char*event,CallBackFunctioncbf,CallBack*p);
AddCallBack(char*event,CallBackStaticFunctioncbsf);
其中,第一个AddCallBack用来将某回调对象的成员函数注册到事件对象的回调表中。
第
二个AddCallBack用来将或某回调类的静态成员函数注册到事件对象的回调表中。
在上参
数表中,event是指向事件名字符串的指针,p是指向回调对象的指针,cbf和cbsf分别是
指向成员函数及静态成员函数(或普通函数)的指针。
当回调函数来自某回调对象Some
Object时,传递成员函数指针应采用如下格式:
(CallBackFunction)&
SomeObject:
M
emberFunctionName;
传递SomeObject类的某静态成员函数指针应采用格式:
(CallBac
kStaticFunction)&
SomeObject:
FunctionName;
传递程序中普通函数指针时,只需传
递函数名即可。
CallBack类的成员函数voidCallBack:
CallCallBack(char*ename,CallDatacallda
ta=NULL)用来调用注册在事件ename上的所有回调函数。
其中,calldata为数据指针(
CallData实际上就是void*,详见程序清单)。
事件对象可通过它向回调对象传递有用的
数据。
该成员函数通常在事件对象的成员函数中调用,因为通常只有事件对象的成员函
数才能改变对象的内部数据,从而使某些事件发生。
成员函数RemoveCallback用来删除注册在事件对象上的回调函数。
它的三个重载版本依
次为:
RemoveCallBack(char*event,CallBackFunctioncbf,CallBack*p);
RemoveCallBack(char*event,CallBackStaticFunctioncbsf
);
RemoveCallBack(char*event);
其中,event,cbf,cbsf,p等参数和成员函数AddCallBack中各参数一样。
第一个RemoveC
allBack用于删除注册在事件event上某回调对象的一个成员函数。
第二个RemoveCallBa
ck用于删除注册在事件event上的某普通函数或某回调类的一个静态成员函数。
第三个R
emoveCallBack用于删除注册在事件event上的全部回调函数。
二、CallBack类的使用方法
使用CallBack类,可按以下步骤进行:
1.确定程序中哪些对象间存在关系,需要建立消息连接。
并确定在各特定消息连接关系
中,哪个对象是事件对象,哪个对象是回调对象。
2.事件对象类和回调对象类都必须从CallBack类继承,以获得回调支持。
3.为事件对象注册回调数据。
包括:
事件名,回调函数名,指向回调对象的指针。
4.当你感兴趣的事件发生时,在事件对象类引发事件的成员函数中调用CallCallBack函
下面是一个具体的例子。
通过它你会对Callback类的使用方法有进一步的了解。
//测试程序文件:
test.cpp
#include"
callback.h"
//“扬声器”类
classSpeaker:
publicCallBack
{
private:
intvolume;
public:
Speaker(intv):
volume(v){}
voidIncreaseVolume(intv)//增加音量成员函数
volume+=v;
if(volume>
20){
//“音量大于20”事件发生了
//调用注册在两事件上的回调函数
CallCallBack("
音量改变了"
音量大于20"
&
volume);
}
voidDecreaseVolume(intv)//降低音量成员函数
volume-=v;
if(volume<
5){//“音量小于5”事件发生了
音量小于5"
};
//“耳朵”类
classEar:
publicCallBack
staticvoidResponse(CallDatacallData)//对“音量改变”的反应
cout<
<
"
音量改变了."
endl;
voidHighVoiceResponse(CallDatacallData)//对高音的反应
”喂!
太吵了!
现在音量是:
*((int*)callData)<
voidLowVoiceResponse(CallDatacallData)//对低音的反应
啊!
我听不清了。
voidmain(void)
Speakers(10);
//现在音量为10
Eare;
//为事件对象s注册回调函数
s.AddCallBack("
音量大于20”,(CallBackFunction)&
Ear:
HighVoiceResponse,&
e);
音量小于5”,(CallBackFunction)&
LowVoiceResponse,&
(CallBackStaticFunction)&
Response);
s.IncreaseVolume(12);
//将音量增加12,现在音量位22
s.DecreaseVolume(20);
//将音量减少20,现在音量位2
运行结果:
音量改变了.
喂!
22
2
在上例中,扬声器对象s为事件对象,耳朵对象e为回调对象。
s上被注册了三个事件
:
“音量改变了”,“音量大于20”,“音量小于5”。
回调函数分别为:
Respo
nse,Ear:
HighVoiceResponse,Ear:
LowVoiceResponse。
当扬声器s通过其成员函数
IncreaseVolume和DecreaseVolume改变音量时,回调对象e会自动作出反应。
可见,通
过使用CallBack类,在对象间建立消息连接已变为一项很简单和优美的工作。
由于笔者水平有限,该类的设计必有不完善之处。
如果您对它感兴趣,笔者可与各位C+
+玩家共同探讨这类问题。
联系方式:
fei_xiang@
附:
程序清单(本程序在MSVC++5.0和TC++3.0上均编译通过)
//回调类的类结构:
callback.h
#ifndef_CALLBACK_H
#define_CALLBACK_H
#include<
stdlib.h>
string.h>
iostream.h>
#defineCALLBACKLIST_INIT_SIZE10
#defineCALLBACKLIST_INCREMENT5
classCallBack;
typedefvoid*CallData;
//回调数据指针类型定义
typedefvoid(CallBack:
*CallBackFunction)(CallData);
//指向回调成员函数的指
针
typedefvoid(*CallBackStaticFunction)(CallData);
//指向静态成员函数或普通函
数的指针类型定义
classEventRecord{
char*eventName;
//回调事件名称
CallBack*pointerToCBO;
//指向回调对象的指针
//指向成员函数的指针和指向静态成员函数(或普通函数)指针的共用体
union{
CallBackFunctionpointerToCBF;
CallBackStaticFunctionpointerToCBSF;
EventRecord(void);
//事件记录类的缺省构造函数
//构造包含成员函数的事件记录
EventRecord(char*ename,CallBack*pCBO,CallBackFunctionpCBF);
//构造包含静态成员函数或普通函数的事件记录
EventRecord(char*ename,CallBackStaticFunctionpCBSF);
~EventRecord(void);
//析构事件记录
voidoperator=(constEventRecord&
er);
//重载赋值运算符
//判断当前事件记录的事件名是否为ename
intoperator==(char*ename)const;
//判断当前事件记录是否和指定事件记录相等
intoperator==(constEventRecord&
er)const;
voidFlush(void);
//将当前事件记录清空
intIsEmpty(void)const;
//判断事件记录是否为空(即事件名是否为空)
friendclassCallBack;
//让CallBack类能访问EventRecord的私有成员;
classCallBack{
EventRecord*callBackList;
//回调事件表
intcurpos;
//当前事件记录位置
intlastpos;
//回调表中最后一空闲位置
intsize;
//回调表的大小
voidMoveFirst(void){curpos=0;
}//将当前记录置为第一条记录
voidMoveNext(void)//将下一条记录置为当前记录
if(curpos==lastpos)return;
curpos++;
//判断回调表是否被遍历完
intEndOfList(void)const{returncurpos==lastpos;
}
CallBack(void);
//构造函数
CallBack(constCallBack&
cb);
//拷贝构造函数
~CallBack(void);
//析构函数
voidoperator=(constCallBack&
//重载赋值运算符
//将回调对象的成员函数、静态成员函数(或普通函数)
//注册为事件对象的回调函数
voidAddCallBack(char*event,CallBackFunctioncbf,CallBack*p);
voidAddCallBack(char*event,CallBackStaticFunctioncbsf);
//删除注册在指定事件上的回调函数
voidRemoveCallBack(char*event,CallBackFunctioncbf,CallBack*p);
voidRemoveCallBack(char*event,CallBackStaticFunctioncbsf);
voidRemoveCallBack(char*event);
//删除某事件的全部记录
//执行注册在某一事件上的所有回调函数
voidCallCallBack(char*event,CallDatacalldata=NULL);
#endif
//回调类的实现:
callback.cpp
//EventRecord类的实现
EventRecord:
EventRecord(void)
eventName=NULL;
pointerToCBO=NULL;
//因为sizeof(CallBackFunction)>
sizeof(CallBackStaticFunction)
pointerToCBF=NULL;
EventRecord(char*ename,CallBack*pCBO,CallBackFunctionpCBF)
pointerToCBO(pCBO),pointerToCBF(pCBF)
eventName=strdup(ename);
EventRecord(char*ename,CallBackStaticFunctionpCBSF)
pointerToCBO(NULL),pointerToCBSF(pCBSF)
~EventRecord(void)
if(eventName)deleteeventName;
voidEventRecord:
operator=(constEventRecord&
er)
if(er.eventName)
eventName=strdup(er.eventName);
else
pointerToCBO=er.pointerToCBO;
pointerToCBF=er.pointerToCBF;
intEventRecord:
operator==(char*ename)const
if((eventName==NULL)||ename==NULL)
returneventName==ename;
returnstrcmp(eventName,ename)==0;
operator==(constEventRecord&
er)const
return(er==eventName)/*er和eventname不能交换位置*/
&
(pointerToCBO==er.pointerToCBO)
(pointerToCBO?
(pointerToCBF==er.pointerToCBF):
(pointerToCBSF==er.pointerToCBSF));
Flush(void)
if(eventName){
deleteeventName;
IsEmpty(void)const
if(eventName==NULL)
return1;
return0;
//Callback类的实现
CallBack:
CallBack(void)
//按初始尺寸为回调表分配内存空间
callBackList=newEventRecord[CALLBACKLIST_INIT_SIZE];
if(!
callBackList){
cerr<
memoryallocationerror."
exit
(1);
size=CALLBACKLIST_INIT_SIZE;
lastpos=0;
curpos=0;
cb):
curpos(cb.curpos),lastpos(cb.lastp
os),size(cb.size)
callBackList=newEventRecord[size];
//一一复制各条事件记录
for(inti=0;
i<
size;
i++)callBackList[i]=cb.callBackList[i];
operator=(constCallBack&
cb)
curpos=cb.curpos;
lastpos=cb.lastpos;
size=cb.size;
delete[]callBackList;
//删除旧的回调表
//重新分配内存空间
~CallBack(void)
AddCallBack(char*event,CallBackFunctionpCBF,CallBack*p
CBO)
//如事件名为空,退出
if((event==NULL)?
1:
(strlen(event)==0))return;
//寻找因删除事件记录而产生的第一个空闲位置,并填写新事件记录
for(intstart=0;
start<
lastpos;
start++)
if(callBackList[start].IsEmpty()){
callBackList[start]=EventRecord(event,pCBO,pCBF);
break;
if(start<
lastpos)return;
//确实存在空闲位置
//没有空闲位置,在回调表后追加新记录
if(lastpos==size)//回调表已满,需“伸长”
EventRecord*tempList=callBackList;
//暂存旧回调表指针
//以一定的步长“伸长”回调表
callBackList=newEventRecord[size+CALLBACKLIST_INCREMENT];
//复制旧回调表中的记录
i++)callBackList[i]=tempList[i];
delete[]tempList;
//删除旧回调表
size+=CALLBACKLIST_INCREMENT;
//记下新回调表的尺寸
//构造新的事件记录并将其填入回调表中
callBac