C++ 事件机制实现

    技术2022-05-20  31

    转自:http://www.cnblogs.com/zhuweisky/archive/2005/09/10/234152.html

     

     

    C++ 事件机制实现

        事件是面向组件开发的必要特性之一,但C++不直接支持事件,没关系,我自己实现了一个,感觉很好用,分享给大家!    最开始打算用函数指针模拟事件,但由于C++中成员函数指针不能和void*相互强转,而且 typedef中不能含有模板,所以才不得已以接口继承实现。这样效果也不错 :)一. 先看看事件接口定义和实现 #ifndef IEVENT_H #define  IEVENT_H /*  以下各基础设施是在C++中事件机制的完整实现,事件是面向组件开发的必要特性之一。   创 作 者:sky 时    间:2005.06.22  修订时间:2005.06.22 */ #include  " ../Collection/SafeArrayList.h " template < class  SenderType , class  ParaType >   class  EventPublisher ; class  NullType{}; //  IEventHandler  是事件处理句柄,预定事件的类从此接口继承以实现事件处理函数 template < class  SenderType , class  ParaType > interface  IEventHandler{ public :  virtual   ~ IEventHandler(){} private :  virtual   void  HandleEvent(SenderType sender ,ParaType para)   =   0  ; friend  class  EventPublisher < SenderType ,ParaType >  ;}; //  IEvent 事件预定方通过此接口预定事件 template < class  SenderType , class  ParaType > interface  IEvent{ public :  virtual   ~ IEvent(){}  virtual   void  Register  (IEventHandler < SenderType ,ParaType >*  handler)  =   0  ;    virtual   void  UnRegister(IEventHandler < SenderType ,ParaType >*  handler)  =   0  ;}; //  IEventActivator 事件发布方通过此接口触发事件 template < class  SenderType , class  ParaType > interface  IEventActivator{ public :  virtual   ~ IEventActivator(){}  virtual   void  Invoke(SenderType sender ,ParaType para)  =   0 ;  virtual   int   HandlerCount()  =   0 ;  virtual  IEventHandler < SenderType ,ParaType >*  GetHandler( int  index)  =   0 ;}; //  IEventPublisher 事件发布方发布事件相当于就是发布一个IEventPublisher派生类的对象 //  不过仅仅将该对象的IEvent接口发布即可。 template < class  SenderType , class  ParaType > interface  IEventPublisher :  public  IEvent < SenderType ,ParaType >  , public  IEventActivator < SenderType ,ParaType >  {}; //  EventPublisher是IEventPublisher的默认实现 template < class  SenderType , class  ParaType > class  EventPublisher : public  IEventPublisher < SenderType ,ParaType > { private : SafeArrayList <  IEventHandler < SenderType ,ParaType >   >  handerList ; IEventHandler < SenderType ,ParaType >*  innerHandler ; public :  void  Register(IEventHandler < SenderType ,ParaType >*  handler)  {   this -> handerList.Add(handler) ; }  void  UnRegister(IEventHandler < SenderType ,ParaType >*  handler) {   this -> handerList.Remove(handler) ; }  void  Invoke(SenderType sender ,ParaType para) {   int  count  =   this -> handerList.Count() ;   for ( int  i = 0  ;i < count ;i ++ )  {   IEventHandler < SenderType ,ParaType >*  handler  =   this -> handerList.GetElement(i) ;   handler -> HandleEvent(sender ,para) ;  } }   int   HandlerCount() {   return   this -> handerList.Count() ; } IEventHandler < SenderType ,ParaType >*  GetHandler( int  index) {   return   this -> handerList.GetElement(index) ; }}; #endif     上面的实现是浅显易懂的,关键是要注意 IEventPublisher的双重身份-- 事件发布方最好发布IEvent指针给外部,而该指针实际指向的是一个EventPublisher对象,这是为了避免外部直接调用IEventActivator接口的方法。二. 一个定时器类Timer,演示如何发布事件。想必大家都知道定时器的用途了哦,这个Timer就像C#中的Timer类一样。 #ifndef TIMER_H #define  TIMER_H /*  Timer 定时器,每经过一段指定时间就触发事件  创 作 者:sky 时    间:2005.06.22  修订时间:2005.06.22 */ #include  " IEvent.h " #include  " Thread.h " void  TimerThreadStart( void *  para) ; class  Timer{ private :  int  spanInMillSecs ;  volatile   bool  isStop ;  volatile   bool  timerThreadDone ;  public : friend  void  TimerThreadStart( void *  para) ; IEvent < Timer *  ,NullType >*  TimerTicked ; Timer( int  span_InMillSecs)  {   this -> isStop  =   true  ;   this -> timerThreadDone  =   true  ;   this -> spanInMillSecs  =  span_InMillSecs ;   this -> TimerTicked  =   new  EventPublisher < Timer *  ,NullType >  ; }   ~ Timer() {   this -> Stop() ;  delete  this -> TimerTicked ; }   void  Start() {   if ( !   this -> isStop)  {    return  ;  }   this -> isStop  =   false  ;  Thread thread ;  thread.Start(TimerThreadStart , this ) ;   // unsigned int  dwThreadId ;   // HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0 , (unsigned int (_stdcall*)(void*))&TimerThreadStart , this, 0, &dwThreadId);       }  void  Stop() {   if (  this -> isStop)  {    return  ;  }     this -> isStop  =   true  ;   // 等待工作线程退出    while ( !   this -> timerThreadDone)  {   Sleep( 200 ) ;  } } private :   void  WorkerThread() {   this -> timerThreadDone  =   false  ;   while ( !   this -> isStop)  {     Sleep( this -> spanInMillSecs) ;    if ( this -> isStop)   {     break  ;   }      NullType nullObj ;   ((EventPublisher < Timer *  ,NullType >* ) this -> TimerTicked) -> Invoke( this  ,nullObj) ;  }   this -> timerThreadDone  =   true  ; }}; void  TimerThreadStart( void *  para){    Timer *  timer  =  (Timer * )para ;    timer -> WorkerThread() ;} #endif

        上面的示例清晰地说明了如何发布一个事件,如何在适当的时候触发事件,接下来看看如何预定事件。三. 预定事件例子

    class  TimerEventExample  : public  IEventHandler < Timer *  ,NullType >  ,CriticalSection{ private : Timer *  timer ;  public : TimerEventExample( int  checkSpan)  {     this -> timer  =   new  Timer(checkSpan) ;   this -> timer -> TimerTicked -> Register( this ) ; }  ~ TimerEventExample() {  delete  this -> timer ; }  private :  // 处理定时事件   void  HandleEvent(Timer *  sender ,NullType para) {  cout << " Time ticked ! " << endl ; }};

        到这里,已经将C++中的事件机制的实现及使用讲清楚了。C#提供了很多便利的基础设施来支持组件开发,而在C++中,这些基础设施需要自己动手来构建,在拥有了这些设施之后,相信使用C++进行组件开发会轻松一点。

     


    最新回复(0)