- 1、本文档共3页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
C++实现事件机制
委托是一种很实用的设计方法,一个模块可以将某些事情委托给其他实体去做,而对于模块本身不需要知道受委托的实体是什么,它只知道这个实体遵循某种接口规范。回调函数可以认为是一种委托,它在Windows编程中起了非常重要的作用。
委托的一个重要应用是事件机制,假设有类A负责加载数据,类B用于实时显示A的加载进度,那么A必须向B引发一些事件,以表明它的加载进度。要实现这种机制可以用观察者模式,Java即使用观察者模式来实现事件监听的。Delphi使用了类似回调函数的技术来实现事件,这样也有一些好处,就是简单高效,对于一些轻量级的应用还是非常合适的。
C++如何实现事件,当然可以用观察者模式来实现,不过这里要介绍另一种方法,就是用成员函数指针,这种方法更类似于Delphi的事件,优点是简单高效。
下面是我写的两个源文件,对通用事件提供了支持,其中涉及到成员函数指针的知识,我就不班门弄斧了,直接给就出源代码如下:
EventUtils.h
#ifndefEVENTUTILS_H_#defineEVENTUTILS_H_
//用于欺骗编译器,传递This指针classCMemFunObj
{
};
//通用函数类型
typedefvoid(CMemFunObj::*PFNMEMFUN)();
//成员函数结构
typedefstructtagMEMBERFUN{CMemFunObj*Self;PFNMEMFUNpfnAddr;
}MEMBERFUN,*PMEMBERFUN;
//生成成员函数结构
MEMBERFUNMakeMemberFun(CMemFunObj*Self,PFNMEMFUNpfnAddr);
//宏:生成成员函数结构
#defineMAKEMEMFUN(Self,pfnAddr)\MakeMemberFun((CMemFunObj*)Self,(PFNMEMFUN)pfnAddr)
//宏:回调成员函数,FunType为具体函数类型,MemFun为成员函数结构
#defineCALLMEMFUN(FunType,MemFun)\(MemFun.Self-*(FunType)MemFun.pfnAddr)
//宏:判断成员函数结构是否有值
#defineISMEMFUNASSIGNED(MemFun)\
(MemFun.Self!=NULL)(MemFun.pfnAddr!=NULL)#endif//EVENTUTILS_H_
EventUtils.cpp
#includeEventUtils.h
//生成成员函数结构
MEMBERFUNMakeMemberFun(CMemFunObj*Self,PFNMEMFUNpfnAddr)
{
MEMBERFUNMemfun;Memfun.pfnAddr=pfnAddr;Memfun.Self=Self;returnMemfun;
}
其中比较有意思的是用CMemFunObj来做对象绑定,这个类会欺骗编译器,使编译将This指针传进成员函数;MEMBERFUN是成员函数结构,一个成员函数要成功调用必须有两个要素,一个是绑定的对象,一个是函数地址,这就是MEMBERFUN的内容。
下面看看如何用这个单元,有一个CRunner类,提供一个Run方法,我们要实现的是监控Run的进度。首先声明CRunner,声明进度事件类型,以及在CRunner保存一个事件类型的成员:
#ifndefRUNNER_H_#defineRUNNER_H_
#includeEventUtils.h
//进度事件类型
typedefvoid(CMemFunObj::*RUNPROCESS)(intnPercent);classCRunner
{
public:
CRunner();
virtual~CRunner();
//设置事件结构
voidSetOnProcess(MEMBERFUNOnRunProcess);
//开始运行
voidRun();private:
MEMBERFUNm_OnRunProcess;
};
#endif//RUNNER_H_
接着实现CRunner,并看看Run如何调用事件:
#includeRunner.h#includestring.h#includewindows.hCRunner::CRunner()
{
memset(m_OnRunProcess,0,sizeof(m_OnRunProcess));
}
CRunner::~CRu
文档评论(0)