最近在工作上遇到一些问题,需要在一个C++的平台上自己实现一些自己定义的“事件”(这里的事件并不是指WINDOWS的事件),在这里记录一下心得:
方案1:
// Event.h
//////////////////////////////////////////////////////////////////////////
// Connect Macro
#define _CONCAT_NAME(s1, s2) s1 ## s2
#define CONCAT_NAME(s1, s2) _CONCAT_NAME(s1, s2)
//////////////////////////////////////////////////////////////////////////
// Event Base Class
class DLL_PUBLIC EventBase
{
private:
string eventName;
protected:
EventBase(const string eventName);
public:
EventBase();
virtual void EventRun();
};
//////////////////////////////////////////////////////////////////////////
// Marco版本 Event Test实现体
#define BEGIN_EVENT(EventName) \
class CONCAT_NAME(Event , _##EventName) : public EventBase \
{ \
public: \
CONCAT_NAME(Event , _##EventName)() : EventBase(string(#EventName)){} \
void EventRun(){ \
#define END_EVENT(EventName) \
}\
}CONCAT_NAME(__Event , _##EventName); \
//////////////////////////////////////////////////////////////////////////
以上是事件的头文件定义,事件实现体是由两个宏组成。并且在最后}CONCAT_NAME(__EventHandler , _##EventName); \这里定义了一个事件变量,他会调用EventBase父类的构造函数,实现向平台注册。父类构造函数实现如下:
//////////////////////////////////////////////////////////////////////////
map eventList;
EventBase::EventBase(const string eventName){
this->eventName= eventName;
eventList[this->eventName] = this;
}
void EventBase::EventRun(){
}
EventBase::EventBase(){
}
//////////////////////////////////////////////////////////////////////////
当平台的插件DLL只需要实现BEGIN_EVENT(...),END_EVENT,例子如下:
BEGIN_EVENT(MyEvent)
cout<<"this is my event!"<END_EVENT
//////////////////////////////////////////////////////////////////////////
当插件DLL被加载起来后,它就会自动向平台注册,在适当的时候,平台就可以运行它所提供的功能。
分析缺点:
1. 这种机制,可以支持很多的事件,但是确是难以维护的,只能靠文档来说明现在有多少事件,事件名是什么....
2. 传参数问题,有的如果需要传参,那也比较麻烦。当然要做是可以的,但给人的感觉不是那么直观了。
方案2:
//////////////////////////////////////////////////////////////////////////
class DLL_PUBLIC EventBase
{
private:
string uniqueTag;
protected:
EventBase(const string& uniqueTag);
public:
EventBase();
// Return the dll UniqueTag.
const string& getUniqueTag();
// Event Function
virtual void Before(){}
virtual void After(){}
};
//////////////////////////////////////////////////////////////////////////
// Event class
#define BEGIN_EVENT \
class Event : public virtual EventBase \
{ \
public: \
Event() : EventBase(TO_STRING(KTESTCASE_PREFIX)) {} \
\
#define END_EVENT \
\
}KTESTCASE_PREFIX; \
方案二不一样的是,基类定义了一些虚函数,它的作用等同上面的事件,在插件DLL里面,可以实现BEGIN_EVENT
void Run(){
cout<<"this is event 'Before' !"< }
END_EVENT
当然也可以在插件里面不是实现,或者只实现其中的一个或两个,因为虚函数有实现体的。
这样做,实现定义相对比较清晰了,所有的事件都列在基类里,以后的人看和改都会比较清除,参数问题也解决了~
阅读(711) | 评论(0) | 转发(0) |