| 订阅 | 在线投稿
分享
 
 
 

C++中建立对象间消息连接的系统方法

2008-06-01 02:07:31  编辑来源:互联网  宽屏版  评论

本文为【C++中建立对象间消息连接的系统方法】的汉字拼音对照版显示拼音

yongguoC++jinxingguomianxiangduixiangchengxushejideyonghudouzhidaochengxuzhongdeduixianghenshaodanducunzaibukaolvduixiangjiandexianghuzuoyongjihushibukenengdesuoyibiaoshiduixiangjiandeguanxihuojianliduixiangjiandexiaoxilianjieshimianxiangduixiangchengxushejideyixiangchongyaorenwu

benwenzhechongcongC++chengxushejidejiaodutichuyizhongjianliduixiangjianxiaoxilianjiedeshiyongfangfajiarunixiangjutilejiemianxiangduixiangchengxushejijishuqingshenyueyouguanzhuanzhu

dajiadouzhidaoduixiangshishujuhefangfadefengzhuangtizaiC++zhongtamenfenbiebiaoxianweishujuchengyuanhechengyuanhanshuchengxushejizhetongguozhixingduixiangdegezhongfangfalaigaibianduixiangdezhuangtaijigaibianduixiangdeshuxingshujuconger使shigaiduixiangfashengmouxieshijiandangyiduixiangfashengmoushijianshitatongchangxuxiangqitaxiangguanduixiangfasongxiaoxiqingqiutamenzuochuyixiechuli zheshifashengshijianbingxiangqitaduixiangqingqiuchulideduixiangbeichengweishijianduixiangerchulishijiandeduixiangbeichengweihuitiaoduixianghuitiaoduixiangduishijiandechulichengweihuitiaohanshu

zaiC++zhongzheyiguochengxiangdangyudangshijianduixiangfashengshijianshitiaoyonghuitiaoduixiangdemouxiechengyuanhanshutongchangdezuofashihuitiaoduixiangxiangshijianduixiangchuandiduixiangzhizhendanzhezhongfangfabutongyongweilejianshaochengxushejidegongzuoliangbenwentichuyizhongjianliduixiangjianxiaoxilianjiedexitongfangfatadesilushijiangshijianfashengqingqiuchulizhixingchulizheyiguochengchouxiangchengyigehuitiaoCallBackleitongguojixuyonghukeyiqingsonghuoqujianliduixiangjianxiaoxilianjiedejizhi

yihuitiaoleideshujujiegoujiqichengyuanhanshu

benwentichudeCallBackleizhichisanzhonghuitiaohanshutamenshihuitiaoduixiangzhongdechengyuanhanshushuyuhuitiaoleidejingtaichengyuanhanshuheputongdeChanshuCallBackleleizhongbaohanyihuitiaohanshubiaocallBackListtayongyujilushijianmingchengzhixianghuitiaohanshujihuitiaoduixiangdezhizhengaibiaodemeiyigejiedianweiyigeshijianjiluEventRecordmeigeshijianjilubaohansangeyushijianmingzhizheneventNamezhixianghuitiaoduixiangdezhizhenpointerToCBOzhixianghuitiaohanshudezhizhenpointerToCBFhuopointerToCBSF(qizhongpointerToCBFzhixianghuitiaoduixiangdechengyuanhanshupointerToCBSFzhixianghuitiaoleidejingtaichengyuanhanshuhuoputonghanshutamentongchuyuyigongyongtinei)CallBackleisuotigongdehuitiaojizhishizheyangdezaishijianduixiangshangzhucehuitiaoduixiangzhongdehuitiaohanshudangshijianfashengshishijianduixiangzaiqihuitiaobiaozhongjiansuobingzhixinghuitiaohanshuconger使shierzhedexiaoxilianjiedeyijianliguanyugaileidejutishixianqingshenyuewenhousuofudechengxuqingdan huitiaoduixiang

shijianduixiang

shijianming huitiaoduixiangzhizhen huitiaohanshuzhizhen

event pointerCBO pointerToCBFhuo

pointerTOCBSF

- - - - - -

AddCallBack: zhuceshijianminghezhixianghuitiaohanshuhuitiaoduixiangdezhizhen

CallCallBack: zaihuitiaobiaozhongjiansuozhucezaizhidingshijianshanghuitiaohanshubingtiaoyongtamen

shijianfashengshitiaoyongCallCallBackhanshu

duishijianeventjinxingchulidechengyuanhanshu

congCallBackleijixudehuitiaobiaocallBackList, chengyuanhanshuAddCallBackheCallCallBack

danghuitiaohanshuweijingtaichengyuanhanshuhuoputongChanshushi pointerToCBOweiNULL

shijianmingshihuitiaobiaocallBackLiszhongdejiansuoyaohaizi

huitiaoduixiangzhongqitachengyuanhanshu

CallBackleidechengyuanhanshuAddCallBackyonglaijianghuitiaohanshuzhucedaoshijianduixiangdehuitiaobiaozhongtayoulianggechongzaibanben

void CallBack::AddCallBack(char *event,CallBackFunction cbf,CallBack *p);

void CallBack::AddCallBack(char *event,CallBackStaticFunction cbsf);

qizhongdiyigeAddCallBackyonglaijiangmouhuitiaoduixiangdechengyuanhanshuzhucedaoshijianduixiangdehuitiaobiaozhongdiergeAddCallBackyonglaijianghuomouhuitiaoleidejingtaichengyuanhanshuzhucedaoshijianduixiangdehuitiaobiaozhongzaishangshenshubiaozhongeventshizhixiangshijianmingzifuchuandezhizhenpshizhixianghuitiaoduixiangdezhizhencbfhecbsffenbieshizhixiangchengyuanhanshujijingtaichengyuanhanshuhuoputonghanshudezhizhendanghuitiaohanshulaizimouhuitiaoduixiangSomeObjectshichuandichengyuanhanshuzhizhenyingcaiyongruxiageshi

CallBackFunction&SomeObject::MemberFunctionName; chuandiSomeObjectleidemoujingtaichengyuanhanshuzhizhenyingcaiyonggeshi

CallBackStaticFunction& SomeObject::FunctionNamechuandichengxuzhongputonghanshuzhizhenshizhixuchuandihanshumingjike

CallBackleidechengyuanhanshuvoid CallBack::CallCallBack(char *ename, CallData calldata = NULL)yonglaitiaoyongzhucezaishijianenameshangdesuoyouhuitiaohanshuqizhongcalldataweishujuzhizhenCallDatashijishangjiushivoid,xiangjianchengxuqingdanshijianduixiangketongguotaxianghuitiaoduixiangchuandiyouyongdeshujugaichengyuanhanshutongchangzaishijianduixiangdechengyuanhanshuzhongtiaoyongyinweitongchangzhiyoushijianduixiangdechengyuanhanshucainenggaibianduixiangdeneibushujuconger使shimouxieshijianfasheng

chengyuanhanshuRemoveCallbackyonglaishanchuzhucezaishijianduixiangshangdehuitiaohanshutadesangechongzaibanbenyiciwei

void CallBack::RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);

void CallBack::RemoveCallBack(char *event,CallBackStaticFunction cbsf);

void CallBack::RemoveCallBack(char *event);

qizhongevent,cbf,cbsf,pdengshenshuhechengyuanhanshuAddCallBackzhonggeshenshuyiyangdiyigeRemoveCallBackyongyushanchuzhucezaishijianeventshangmouhuitiaoduixiangdeyigechengyuanhanshudiergeRemoveCallBackyongyushanchuzhucezaishijianeventshangdemouputonghanshuhuomouhuitiaoleideyigejingtaichengyuanhanshudisangeRemoveCallBackyongyushanchuzhucezaishijianeventshangdequanbuhuitiaohanshu

erCallBackleide使shiyongfangfa

使shiyongCallBackleikeanyixiabuzhoujinxing

1quedingchengxuzhongnaxieduixiangjiancunzaiguanxixuyaojianlixiaoxilianjiebingquedingzaigetedingxiaoxilianjieguanxizhongnageduixiangshishijianduixiangnageduixiangshihuitiaoduixiang

2shijianduixiangleihehuitiaoduixiangleidoubixucongCallBackleijixuyihuodehuitiaozhichi

3weishijianduixiangzhucehuitiaoshujubaokuoshijianminghuitiaohanshumingzhixianghuitiaoduixiangdezhizhen

4dangniganaihaodeshijianfashengshizaishijianduixiangleiyinfashijiandechengyuanhanshuzhongtiaoyongCallCallBackhanshu

xiamianshiyigejutidelizitongguotanihuiduiCallbackleide使shiyongfangfayoujinyibudelejie

file://ceshichengxuwenjiantest.cpp

#include"callback.h"

file://yangshengqilei

class Speaker:public CallBack

{

private:

int volume;

public:

Speaker(int v): volume(v) {}

void IncreaseVolume(int v) file://zengjiayinliangchengyuanhanshu

{

volume += v;

if(volume >20){ file://yinliangdayu20shijianfashengle

file://tiaoyongzhucezailiangshijianshangdehuitiaohanshu

CallCallBack("yinlianggaibianle");

CallCallBack("yinliangdayu20", &volume);

}

}

void DecreaseVolume(int v) file://jiangdiyinliangchengyuanhanshu

{

volume -= v;

if(volume < 5){ file://yinliangxiaoyu5shijianfashengle

file://tiaoyongzhucezailiangshijianshangdehuitiaohanshu

CallCallBack("yinlianggaibianle");

CallCallBack("yinliangxiaoyu5", &volume);

}

}

};

file://erduolei

class Ear : public CallBack

{

public:

static void Response(CallData callData) file://duiyinlianggaibiandefanying

{

cout<<"yinlianggaibianle."< }

void HighVoiceResponse(CallData callData)//duigaoyindefanying

{

cout<<weitaichaolexianzaiyinliangshi"<<*((int *)callData)< }

void LowVoiceResponse(CallData callData)// duidiyindefanying

{

cout<<"awotingbuqinglexianzaiyinliangshi"<<*((int *)callData)< }

};

void main(void)

{

Speaker s(10); file://xianzaiyinliangwei10

Ear e;

file://weishijianduixiangszhucehuitiaohanshu

s.AddCallBack("yinliangdayu20,(CallBackFunction)&Ear::HighVoiceResponse,&e);

s.AddCallBack("yinliangxiaoyu5,(CallBackFunction)&Ear::LowVoiceResponse,&e);

s.AddCallBack("yinlianggaibianle",(CallBackStaticFunction)&Ear::Response);

s.IncreaseVolume(12);//jiangyinliangzengjia12xianzaiyinliangwei22

s.DecreaseVolume(20);//jiangyinliangjianshao20xianzaiyinliangwei2

}

yunxingjieguo

yinlianggaibianle.

weitaichaolexianzaiyinliangshi22

yinlianggaibianle.

awotingbuqinglexianzaiyinliangshi2

zaishanglizhongyangshengqiduixiangsweishijianduixiangerduoduixiangeweihuitiaoduixiangsshangbeizhucelesangeshijianyinlianggaibianleyinliangdayu20yinliangxiaoyu5 huitiaohanshufenbieweiEar::Response Ear::HighVoiceResponseEar::LowVoiceResponsedangyangshengqistongguoqichengyuanhanshuIncreaseVolumehe DecreaseVolumegaibianyinliangshihuitiaoduixiangehuizidongzuochufanyingkejiantongguo使shiyongCallBackleizaiduixiangjianjianlixiaoxilianjieyibianweiyixianghenjiandanhemeilidegongzuo

youyubizheshuipingyouxiangaileideshejibiyoubuwanshanzhichujiaruninduitaganaihaobizhekeyugeweiC++wanjiagongtongtantaozheleiwenti

lianxifangshi:fei_xiang@263.net

gengduoneirongqingkanC/C++jishuzhuanti C/C++jinjiejishuwendang xitonganquanshezhizhuantihuo

fuchengxuqingdanbenchengxuzaiMS VC++5.0heTC++3.0shangyunbianyitongguo

file://huitiaoleideleijiegou:callback.h

#ifndef _CALLBACK_H

#define _CALLBACK_H

#include<stdlib.h>

#include<string.h>

#include<iostream.h>

#define CALLBACKLIST_INIT_SIZE 10

#define CALLBACKLIST_INCREMENT 5

class CallBack;

typedef void *CallData;//huitiaoshujuzhizhenleixingdingyi

typedef void (CallBack::*CallBackFunction)(CallData); file://zhixianghuitiaochengyuanhanshudezhizhen

typedef void (*CallBackStaticFunction)(CallData); file://zhixiangjingtaichengyuanhanshuhuoputonghanshudezhizhenleixingdingyi

class EventRecord{

private:

char *eventName; file://huitiaoshijianmingcheng

CallBack *pointerToCBO;//zhixianghuitiaoduixiangdezhizhen

file://zhixiangchengyuanhanshudezhizhenhezhixiangjingtaichengyuanhanshuhuoputonghanshuzhizhendegongyongti

union{

CallBackFunction pointerToCBF;

CallBackStaticFunction pointerToCBSF;

};

public:

EventRecord(void); file://shijianjiluleidequeshenggouzaohanshu

file://gouzaobaohanchengyuanhanshudeshijianjilu

EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);

file://gouzaobaohanjingtaichengyuanhanshuhuoputonghanshudeshijianjilu

EventRecord(char *ename,CallBackStaticFunction pCBSF);

~EventRecord(void);//xigoushijianjilu

void operator = (const EventRecord& er);//chongzaifuzhiyunsuanfu

file://pandingdangqianshijianjiludeshijianmingshifouweiename

int operator == (char *ename) const;

file://pandingdangqianshijianjilushifouhezhidingshijianjiluxiangdeng

int operator == (const EventRecord& er) const;

void Flush(void); file://jiangdangqianshijianjiluqingkong

int IsEmpty(void) const;//pandingshijianjilushifouweikongjishijianmingshifouweikong

friend class CallBack; file://rangCallBackleineng访fangwenEventRecorddesiyouchengyuan

};

class CallBack {

private:

EventRecord *callBackList; file://huitiaoshijianbiao

int curpos; file://dangqianshijianjiluweizhi

int lastpos; file://huitiaobiaozhongzuihouyikongxianweizhi

int size; file://huitiaobiaodedaxiao

void MoveFirst(void) { curpos = 0; }//jiangdangqianjiluzhiweidiyitiaojilu

void MoveNext(void) file://jiangxiayitiaojiluzhiweidangqianjilu

{

if(curpos == lastpos) return;

curpos++;

}

file://pandinghuitiaobiaoshifoubeibianliwan

int EndOfList(void) const { return curpos == lastpos; }

public:

CallBack(void);//gouzaohanshu

CallBack(const CallBack& cb);//kaobeigouzaohanshu

~CallBack(void);//xigouhanshu

void operator = (const CallBack& cb);// chongzaifuzhiyunsuanfu

file://jianghuitiaoduixiangdechengyuanhanshujingtaichengyuanhanshuhuoputonghanshu file://zhuceweishijianduixiangdehuitiaohanshu

void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);

void AddCallBack(char *event,CallBackStaticFunction cbsf);

file://shanchuzhucezaizhidingshijianshangdehuitiaohanshu

void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);

void RemoveCallBack(char *event,CallBackStaticFunction cbsf);

void RemoveCallBack(char *event);// shanchumoushijiandequanbujilu

file://zhixingzhucezaimouyishijianshangdesuoyouhuitiaohanshu

void CallCallBack(char *event, CallData calldata = NULL);

};

#endif

file://huitiaoleideshixian:callback.cpp

#include"callback.h"

file://EventRecordleideshixian

EventRecord::EventRecord(void)

{

eventName = NULL;

pointerToCBO = NULL;

file://yinweisizeof(CallBackFunction) > sizeof(CallBackStaticFunction)

pointerToCBF = NULL;

}

EventRecord::EventRecord(char *ename, CallBack *pCBO, CallBackFunction pCBF)

:pointerToCBO(pCBO), pointerToCBF(pCBF)

{

eventName = strdup(ename);

}

EventRecord::EventRecord(char *ename, CallBackStaticFunction pCBSF)

:pointerToCBO(NULL), pointerToCBSF(pCBSF)

{

eventName = strdup(ename);

}

EventRecord::~EventRecord(void)

{

if(eventName) delete eventName;

}

void EventRecord::operator = (const EventRecord& er)

{

if(er.eventName)

eventName = strdup(er.eventName);

else

eventName = NULL;

pointerToCBO = er.pointerToCBO;

pointerToCBF = er.pointerToCBF;

}

int EventRecord::operator == (char *ename) const

{

if((eventName == NULL)ename == NULL)

return eventName == ename;

else

return strcmp(eventName,ename) == 0;

}

int EventRecord::operator == (const EventRecord& er) const

{

return (er == eventName) /*erheeventnamebunengjiaohuanweizhi*/

&&(pointerToCBO == er.pointerToCBO)

&&(pointerToCBO ?

(pointerToCBF == er.pointerToCBF):

(pointerToCBSF == er.pointerToCBSF));

}

void EventRecord::Flush(void)

{

if(eventName){

delete eventName;

eventName = NULL;

}

pointerToCBO = NULL;

pointerToCBF = NULL;

}

int EventRecord::IsEmpty(void) const

{

if(eventName == NULL)

return 1;

else

return 0;

}

file://Callbackleideshixian

CallBack::CallBack(void)

{

file://anchushichicunweihuitiaobiaofenpeineicunkongjian

callBackList = new EventRecord[CALLBACKLIST_INIT_SIZE];

if(!callBackList){

cerr<<"CallBack: memory allocation error."<<endl;

exit(1);

}

size = CALLBACKLIST_INIT_SIZE;

lastpos = 0;

curpos = 0;

}

CallBack::CallBack(const CallBack& cb): curpos(cb.curpos),lastpos(cb.lastpos),size(cb.size)

{

callBackList = new EventRecord[size];

if(!callBackList){

cerr<<"CallBack: memory allocation error."<<endl;

exit(1);

}

file://yiyifuzhigetiaoshijianjilu

for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];

}

void CallBack::operator = (const CallBack& cb)

{

curpos = cb.curpos;

lastpos = cb.lastpos;

size = cb.size;

delete [] callBackList;//shanchujiudehuitiaobiao

callBackList = new EventRecord[size];//chongxinfenpeineicunkongjian

if(!callBackList){

cerr<<"CallBack: memory allocation error."<<endl;

exit(1);

}

file://yiyifuzhigetiaoshijianjilu

for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];

}

CallBack::~CallBack(void)

{

delete [] callBackList;

}

void CallBack::AddCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)

{

file://rushijianmingweikong退tuichu

if( (event == NULL)?1:(strlen(event) == 0)) return;

file://xunzhaoyinshanchushijianjiluerchanshengdediyigekongxianweizhibingtianxiexinshijianjilu

for(int start=0;start<lastpos;start++)

if(callBackList[start].IsEmpty()){

callBackList[start] = EventRecord(event,pCBO,pCBF);

break;

}

if(start < lastpos) return; file://queshicunzaikongxianweizhi

file://meiyoukongxianweizhizaihuitiaobiaohouzhuijiaxinjilu

if(lastpos == size) file://huitiaobiaoyimanxushenchang

{

EventRecord *tempList = callBackList;//zancunjiuhuitiaobiaozhizhen

file://yiyidingdebuchangshenchanghuitiaobiao

callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];

if(!callBackList){

cerr<<"CallBack: memory allocation error."<<endl;

exit(1);

}

file://fuzhijiuhuitiaobiaozhongdejilu

for(int i = 0; i < size; i++) callBackList[i] = tempList[i];

delete [] tempList;//shanchujiuhuitiaobiao

size += CALLBACKLIST_INCREMENT;//jixiaxinhuitiaobiaodechicun

}

file://gouzaoxindeshijianjilubingjiangqitianruhuitiaobiaozhong

callBackList[lastpos] = EventRecord(event,pCBO,pCBF);

lastpos++;

}

void CallBack::AddCallBack(char *event,CallBackStaticFunction pCBSF)

{

if( (event == NULL)?1:(strlen(event) == 0)) return;

for(int start=0;start<lastpos;start++)

if(callBackList[start].IsEmpty()){

callBackList[start] = EventRecord(event,pCBSF);

break;

}

if(start < lastpos) return; file://a hole is found

if(lastpos == size) file://event list is insufficient

{

EventRecord *tempList = callBackList;

callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];

if(!callBackList){

cerr<<"CallBack: memory allocation error."<<endl;

exit(1);

}

for(int i = 0; i < size; i++) callBackList[i] = tempList[i];

delete [] tempList;

size += CALLBACKLIST_INCREMENT;

}

callBackList[lastpos] = EventRecord(event,pCBSF);

lastpos++;

}

file://shanchuzhucezaizhidingshijianshangdechengyuanhanshu

void CallBack::RemoveCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)

{

if( (event == NULL)?1:(strlen(event) == 0)) return;

EventRecord er(event,pCBO,pCBF);

for(int i = 0; i < lastpos; i++)

if(callBackList[i] == er) callBackList[i].Flush();

}

file://shanchuzhucezaizhidingshijianshangdejingtaichengyuanhanshuhuoputonghanshu

void CallBack::RemoveCallBack(char *event,CallBackStaticFunction pCBSF)

{

if( (event == NULL)?1:(strlen(event) == 0)) return;

EventRecord er(event,pCBSF);

for(int i = 0; i < lastpos; i++)

if(callBackList[i] == er) callBackList[i].Flush();

}

file://shanchuzhucezaizhidingshijianshangdesuoyouhuitiaohanshu

void CallBack::RemoveCallBack(char *event)

{

if( (event == NULL)?1:(strlen(event) == 0)) return;

for(int i = 0; i < lastpos; i++)

if(callBackList[i] == event) callBackList[i].Flush();

}

void CallBack::CallCallBack(char *event, CallData callData)

{

if( (event == NULL)?1:(strlen(event) == 0)) return;

CallBack *pCBO;

CallBackFunction pCBF;

CallBackStaticFunction pCBSF;

MoveFirst();

while(!EndOfList())

{

file://rudangqianshijianjiluhezhidingshijianbupipeizhuanruxiayitiaojilujixuxunhuan

if(!(callBackList[curpos] == event))

{

MoveNext();

continue;

}

file://ruzhaodaopipeijilu

pCBO = callBackList[curpos].pointerToCBO;

file://rushijianjiluzhonghuitiaoduixiangzhizhenweikongshuominggaijiluzhongbaocundeshijingtaihanshuzhizhen

if(pCBO == NULL){

pCBSF = callBackList[curpos].pointerToCBSF;

pCBSF(callData);//tiaoyonggaijingtaihuitiaohanshu

}

else file://rushijianjiluzhonghuitiaoduixiangzhizhenfeikongshuominggaijiluzhongbaocundeshichengyuanhanshuzhizhen

{

pCBF = callBackList[curpos].pointerToCBF;

(pCBO->*pCBF)(callData);// tiaoyonggaihuitiaoduixiangdechengyuanhanshu

}

MoveNext();

}

} gengduoneirongqingkanC/C++jishuzhuanti C/C++jinjiejishuwendang xitonganquanshezhizhuanti

huo

原文
  用过C++进行过面向对象程序设计的用户都知道,程序中的对象很少单独存在。不考虑对象间的相互作用几乎是不可能的。所以,标识对象间的关系或建立对象间的消息连接是面向对象程序设计的一项重要任务。 本文着重从C++程序设计的角度,提出一种建立对象间消息连接的实用方法。假如你想具体了解面向对象程序设计技术,请参阅有关专著。    大家都知道对象是数据和方法的封装体。在C++中,它们分别表现为数据成员和成员函数。程序设计者通过执行对象的各种方法,来改变对象的状态(即改变对象的属性数据)。从而使该对象发生某些“事件”。当一对象发生某事件时,它通常需向其它相关对象发送“消息”,请求它们作出一些处理。 这时,发生事件并向其它对象请求处理的对象被称为“事件对象”,而处理事件的对象被称为“回调对象”。回调对象对事件的处理称为“回调函数”。    在C++中,这一过程相当于:当事件对象发生事件时,调用回调对象的某些成员函数。通常的作法是回调对象向事件对象传递对象指针。但这种方法不通用。为了减少程序设计的工作量,本文提出一种建立对象间消息连接的系统方法。它的思路是:将“事件发生→请求处理→执行处理”这一过程抽象成一个“回调”(CallBack)类。通过继续,用户可以轻松获取建立对象间消息连接的机制。    一、回调类的数据结构及其成员函数    本文提出的CallBack类支持三种回调函数。它们是:回调对象中的成员函数,属于回调类的静态成员函数和普通的C函数。CallBackle类中包含一回调函数表callBackList。它用于记录事件名称,指向回调函数及回调对象的指针。该表的每一个节点为一个事件记录EventRecord。每个事件记录包含三个域:事件名指针eventName,指向回调对象的指针pointerToCBO,指向回调函数的指针pointerToCBF或pointerToCBSF(其中,pointerToCBF指向回调对象的成员函数,pointerToCBSF指向回调类的静态成员函数或普通函数。它们同处于一共用体内)。CallBack类所提供的回调机制是这样的:在事件对象上注册回调对象中的回调函数;当事件发生时,事件对象在其回调表中检索并执行回调函数。从而使二者的消息连接得以建立。(关于该类的具体实现,请参阅文后所附的程序清单) 回调对象   事件对象    事件名 回调对象指针 回调函数指针 “event” pointerCBO pointerToCBF或 pointerTOCBSF - - - - - -    AddCallBack: 注册事件名和指向回调函数,回调对象的指针    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上的全部回调函数。   二、CallBack类的使用方法    使用CallBack类,可按以下步骤进行:    1.确定程序中哪些对象间存在关系,需要建立消息连接。并确定在各特定消息连接关系中,哪个对象是事件对象,哪个对象是回调对象。    2.事件对象类和回调对象类都必须从CallBack类继续,以获得回调支持。    3.为事件对象注册回调数据。包括:事件名,回调函数名,指向回调对象的指针。    4.当你感爱好的事件发生时,在事件对象类引发事件的成员函数中调用CallCallBack函数。    下面是一个具体的例子。通过它你会对Callback类的使用方法有进一步的了解。 file://测试程序文件:test.cpp #include"callback.h" file://“扬声器”类 class Speaker:public CallBack {   private:    int volume;   public:    Speaker(int v): volume(v) {}    void IncreaseVolume(int v) file://增加音量成员函数    {     volume += v;     if(volume >20){ file://“音量大于20”事件发生了      file://调用注册在两事件上的回调函数      CallCallBack("音量改变了");      CallCallBack("音量大于20", &volume);     }    }   void DecreaseVolume(int v) file://降低音量成员函数   {    volume -= v;    if(volume < 5){ file://“音量小于5”事件发生了     file://调用注册在两事件上的回调函数     CallCallBack("音量改变了");     CallCallBack("音量小于5", &volume);    }   } }; file://“耳朵”类 class Ear : public CallBack {   public:    static void Response(CallData callData) file://对“音量改变”的反应    {     cout<<"音量改变了."<   }    void HighVoiceResponse(CallData callData)//对高音的反应    {     cout<<”喂!太吵了!现在音量是:"<<*((int *)callData)<   }    void LowVoiceResponse(CallData callData)// 对低音的反应    {     cout<<"啊!我听不清了。现在音量是:"<<*((int *)callData)<   } }; void main(void) {   Speaker s(10); file://现在音量为10   Ear e;   file://为事件对象s注册回调函数   s.AddCallBack("音量大于20”,(CallBackFunction)&Ear::HighVoiceResponse,&e);   s.AddCallBack("音量小于5”,(CallBackFunction)&Ear::LowVoiceResponse,&e);   s.AddCallBack("音量改变了",(CallBackStaticFunction)&Ear::Response);   s.IncreaseVolume(12);//将音量增加12,现在音量位22   s.DecreaseVolume(20);//将音量减少20,现在音量位2 }    运行结果:    音量改变了.    喂!太吵了!现在音量是:22    音量改变了.    啊!我听不清了。现在音量是:2    在上例中,扬声器对象s为事件对象,耳朵对象e为回调对象。。s上被注册了三个事件:“音量改变了”,“音量大于20”,“音量小于5”。 回调函数分别为:Ear::Response, Ear::HighVoiceResponse,Ear::LowVoiceResponse。当扬声器s通过其成员函数IncreaseVolume和 DecreaseVolume改变音量时,回调对象e会自动作出反应。可见,通过使用CallBack类,在对象间建立消息连接已变为一项很简单和美丽的工作。    由于笔者水平有限,该类的设计必有不完善之处。假如您对它感爱好,笔者可与各位C++玩家共同探讨这类问题。    联系方式:fei_xiang@263.net 更多内容请看C/C++技术专题 C/C++进阶技术文档 系统安全设置专题,或   附:程序清单(本程序在MS VC++5.0和TC++3.0上均编译通过) file://回调类的类结构:callback.h #ifndef _CALLBACK_H #define _CALLBACK_H #include<stdlib.h> #include<string.h> #include<iostream.h> #define CALLBACKLIST_INIT_SIZE 10 #define CALLBACKLIST_INCREMENT 5 class CallBack; typedef void *CallData;//回调数据指针类型定义 typedef void (CallBack::*CallBackFunction)(CallData); file://指向回调成员函数的指针 typedef void (*CallBackStaticFunction)(CallData); file://指向静态成员函数或普通函数的指针类型定义 class EventRecord{   private:    char *eventName; file://回调事件名称    CallBack *pointerToCBO;//指向回调对象的指针    file://指向成员函数的指针和指向静态成员函数(或普通函数)指针的共用体    union{     CallBackFunction pointerToCBF;     CallBackStaticFunction pointerToCBSF;    };   public:    EventRecord(void); file://事件记录类的缺省构造函数    file://构造包含成员函数的事件记录    EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);    file://构造包含静态成员函数或普通函数的事件记录    EventRecord(char *ename,CallBackStaticFunction pCBSF);    ~EventRecord(void);//析构事件记录    void operator = (const EventRecord& er);//重载赋值运算符    file://判定当前事件记录的事件名是否为ename    int operator == (char *ename) const;    file://判定当前事件记录是否和指定事件记录相等    int operator == (const EventRecord& er) const;    void Flush(void); file://将当前事件记录清空    int IsEmpty(void) const;//判定事件记录是否为空(即事件名是否为空)    friend class CallBack; file://让CallBack类能访问EventRecord的私有成员; }; class CallBack {   private:    EventRecord *callBackList; file://回调事件表    int curpos; file://当前事件记录位置    int lastpos; file://回调表中最后一空闲位置    int size; file://回调表的大小    void MoveFirst(void) { curpos = 0; }//将当前记录置为第一条记录    void MoveNext(void) file://将下一条记录置为当前记录    {     if(curpos == lastpos) return;     curpos++;    }    file://判定回调表是否被遍历完    int EndOfList(void) const { return curpos == lastpos; }     public:      CallBack(void);//构造函数      CallBack(const CallBack& cb);//拷贝构造函数      ~CallBack(void);//析构函数    void operator = (const CallBack& cb);// 重载赋值运算符    file://将回调对象的成员函数、静态成员函数(或普通函数) file://注册为事件对象的回调函数    void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);    void AddCallBack(char *event,CallBackStaticFunction cbsf);    file://删除注册在指定事件上的回调函数    void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);    void RemoveCallBack(char *event,CallBackStaticFunction cbsf);    void RemoveCallBack(char *event);// 删除某事件的全部记录    file://执行注册在某一事件上的所有回调函数    void CallCallBack(char *event, CallData calldata = NULL);   };   #endif   file://回调类的实现:callback.cpp   #include"callback.h"   file://EventRecord类的实现   EventRecord::EventRecord(void)   {    eventName = NULL;    pointerToCBO = NULL;    file://因为sizeof(CallBackFunction) > sizeof(CallBackStaticFunction)    pointerToCBF = NULL;   }   EventRecord::EventRecord(char *ename, CallBack *pCBO, CallBackFunction pCBF)   :pointerToCBO(pCBO), pointerToCBF(pCBF)   {    eventName = strdup(ename);   }   EventRecord::EventRecord(char *ename, CallBackStaticFunction pCBSF)   :pointerToCBO(NULL), pointerToCBSF(pCBSF)   {    eventName = strdup(ename);   }   EventRecord::~EventRecord(void)   {    if(eventName) delete eventName;   }   void EventRecord::operator = (const EventRecord& er)   {    if(er.eventName)     eventName = strdup(er.eventName);    else     eventName = NULL;     pointerToCBO = er.pointerToCBO;     pointerToCBF = er.pointerToCBF;   }   int EventRecord::operator == (char *ename) const   {    if((eventName == NULL)ename == NULL)     return eventName == ename;    else     return strcmp(eventName,ename) == 0;   }   int EventRecord::operator == (const EventRecord& er) const   {    return (er == eventName) /*er和eventname不能交换位置*/      &&(pointerToCBO == er.pointerToCBO)      &&(pointerToCBO ?      (pointerToCBF == er.pointerToCBF):      (pointerToCBSF == er.pointerToCBSF));   }   void EventRecord::Flush(void)   {    if(eventName){     delete eventName;     eventName = NULL;    }    pointerToCBO = NULL;    pointerToCBF = NULL;   }   int EventRecord::IsEmpty(void) const   {    if(eventName == NULL)     return 1;    else     return 0;   }   file://Callback类的实现   CallBack::CallBack(void)   {    file://按初始尺寸为回调表分配内存空间    callBackList = new EventRecord[CALLBACKLIST_INIT_SIZE];    if(!callBackList){     cerr<<"CallBack: memory allocation error."<<endl;     exit(1);    }    size = CALLBACKLIST_INIT_SIZE;    lastpos = 0;    curpos = 0;   }   CallBack::CallBack(const CallBack& cb): curpos(cb.curpos),lastpos(cb.lastpos),size(cb.size)   {    callBackList = new EventRecord[size];    if(!callBackList){     cerr<<"CallBack: memory allocation error."<<endl;     exit(1);    }    file://一一复制各条事件记录    for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];   }   void CallBack::operator = (const CallBack& cb)   {    curpos = cb.curpos;    lastpos = cb.lastpos;    size = cb.size;    delete [] callBackList;//删除旧的回调表    callBackList = new EventRecord[size];//重新分配内存空间    if(!callBackList){     cerr<<"CallBack: memory allocation error."<<endl;     exit(1);    }    file://一一复制各条事件记录    for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];   }   CallBack::~CallBack(void)   {    delete [] callBackList;   }   void CallBack::AddCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)   {    file://如事件名为空,退出    if( (event == NULL)?1:(strlen(event) == 0)) return;    file://寻找因删除事件记录而产生的第一个空闲位置,并填写新事件记录    for(int start=0;start<lastpos;start++)     if(callBackList[start].IsEmpty()){      callBackList[start] = EventRecord(event,pCBO,pCBF);      break;     }     if(start < lastpos) return; file://确实存在空闲位置     file://没有空闲位置,在回调表后追加新记录     if(lastpos == size) file://回调表已满,需“伸长”     {      EventRecord *tempList = callBackList;//暂存旧回调表指针      file://以一定的步长“伸长”回调表      callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];      if(!callBackList){       cerr<<"CallBack: memory allocation error."<<endl;       exit(1);      }      file://复制旧回调表中的记录      for(int i = 0; i < size; i++) callBackList[i] = tempList[i];      delete [] tempList;//删除旧回调表      size += CALLBACKLIST_INCREMENT;//记下新回调表的尺寸     }     file://构造新的事件记录并将其填入回调表中     callBackList[lastpos] = EventRecord(event,pCBO,pCBF);     lastpos++;    }    void CallBack::AddCallBack(char *event,CallBackStaticFunction pCBSF)    {     if( (event == NULL)?1:(strlen(event) == 0)) return;     for(int start=0;start<lastpos;start++)      if(callBackList[start].IsEmpty()){       callBackList[start] = EventRecord(event,pCBSF);       break;      }     if(start < lastpos) return; file://a hole is found     if(lastpos == size) file://event list is insufficient     {      EventRecord *tempList = callBackList;      callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];      if(!callBackList){       cerr<<"CallBack: memory allocation error."<<endl;       exit(1);      }      for(int i = 0; i < size; i++) callBackList[i] = tempList[i];      delete [] tempList;      size += CALLBACKLIST_INCREMENT;     }    callBackList[lastpos] = EventRecord(event,pCBSF);    lastpos++;   }   file://删除注册在指定事件上的成员函数   void CallBack::RemoveCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)   {    if( (event == NULL)?1:(strlen(event) == 0)) return;    EventRecord er(event,pCBO,pCBF);    for(int i = 0; i < lastpos; i++)     if(callBackList[i] == er) callBackList[i].Flush();   }   file://删除注册在指定事件上的静态成员函数或普通函数   void CallBack::RemoveCallBack(char *event,CallBackStaticFunction pCBSF)   {    if( (event == NULL)?1:(strlen(event) == 0)) return;    EventRecord er(event,pCBSF);    for(int i = 0; i < lastpos; i++)     if(callBackList[i] == er) callBackList[i].Flush();   }   file://删除注册在指定事件上的所有回调函数   void CallBack::RemoveCallBack(char *event)   {    if( (event == NULL)?1:(strlen(event) == 0)) return;    for(int i = 0; i < lastpos; i++)     if(callBackList[i] == event) callBackList[i].Flush();   }   void CallBack::CallCallBack(char *event, CallData callData)   {    if( (event == NULL)?1:(strlen(event) == 0)) return;    CallBack *pCBO;    CallBackFunction pCBF;    CallBackStaticFunction pCBSF;    MoveFirst();    while(!EndOfList())    {     file://如当前事件记录和指定事件不匹配,转入下一条记录继续循环     if(!(callBackList[curpos] == event))     {      MoveNext();      continue;     }     file://如找到匹配记录     pCBO = callBackList[curpos].pointerToCBO;     file://如事件记录中回调对象指针为空,说明该记录中保存的是静态函数指针     if(pCBO == NULL){      pCBSF = callBackList[curpos].pointerToCBSF;      pCBSF(callData);//调用该静态回调函数     }     else file://如事件记录中回调对象指针非空,说明该记录中保存的是成员函数指针     {      pCBF = callBackList[curpos].pointerToCBF;      (pCBO->*pCBF)(callData);// 调用该回调对象的成员函数     }     MoveNext();    }   } 更多内容请看C/C++技术专题 C/C++进阶技术文档 系统安全设置专题, 或
󰈣󰈤
 
 
 
>>返回首页<<
 
 
 转载本文
 UBB代码 HTML代码
复制到剪贴板...
 
 热帖排行
 
 
王朝网络微信公众号
微信扫码关注本站公众号wangchaonetcn
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有