Chinaunix首页 | 论坛 | 博客
  • 博客访问: 482240
  • 博文数量: 35
  • 博客积分: 4010
  • 博客等级: 上校
  • 技术积分: 1234
  • 用 户 组: 普通用户
  • 注册时间: 2005-10-06 22:48
文章分类

全部博文(35)

文章存档

2008年(35)

我的朋友

分类: C/C++

2008-10-26 20:54:02

最近在工作上遇到一些问题,需要在一个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) |
给主人留下些什么吧!~~