好久没用C++了,今天整理以前写的代码,发现一个以前用C++写的Event模板类,
虽然写出来之后都没怎么用过,不过个人感觉应该蛮好用的,这里贴出来,大家帮忙找找碴。
1,使用方法
先看看这个Event类怎么使用的吧:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <stdio.h> // 这里也可以这样使用 |
简单说明一下示例程序,程序里有两个类,指挥官Commander类和士兵Soldier类
Commander类中定义了一个事件对象:
EventIntIntType TargetChangedEvent; // 定义事件
这个EventIntIntType是在前面typedef的模板类型定义:
typedef Event<TYPE_LIST2(int, int)> EventIntIntType;
这个TYPE_LIST2是一个宏定义,就是类型列表,
因为这里定义的是两个int参数的事件,所以使用TYPE_LIST2,
当然也有,
TYPE_LIST1
TYPE_LIST2
……
最多到
TYPE_LIST6
(我想应该够用了吧?)
对了,如果这个Event不需要参数,那么使用Event<void>。
(这个<void>有没有可能去掉?!)
然后Soldier类的构造函数中,把自己的
void ChangeTarget(int x, int y)函数注册到Commander的TargetChangedEvent事件中;
// 监听指挥官的广播
_commander->TargetChangedEvent.Add(EventIntIntType::Handler(this, &Soldier::ChangeTarget)); // 注册事件
这里其实就是新建了一个Functor<int,int>,加到Event<int,int>的链表中,
为了方便使用,我这里是在Event中加了一个Handler类型,
当然你也可以直接新建一个这种类型的Functor加进去,
// 这里也可以这样使用
// Functor<void, TYPE_LIST2(int, int)> functor(this, &Soldier::ChangeTarget);
// _commander->TargetChangedEvent.Add(functor);
另外要记住,在Soldier类的析构函数中,把自己注册的Event注销掉,
_commander->TargetChangedEvent.Remove(EventIntIntType::Handler(this, &Soldier::ChangeTarget)); // 注消事件
看到这里,你可能会有个疑问:为什么这里还需要新建一个Functor传进去?
因为注销的时候,其实是比较Functor是否相等,如果Functor相等,那么才会注销,
Functor比较是比较的对象指针和成员函数指针,只要两者相等,就表示Functor是相等的。
所以这里还是需要再传个Functor进去比较的。
在Commander中,如果需要广播事件,只要这样调用就可以了:
// 所有听到这个广播的士兵,向目标进发
TargetChangedEvent(x, y); // 广播事件
怎么样?用法很简单吧?!
上面代码是可以直接编译运行的,只要把下面的Functor.h和Event.h文件加到工程里就可以了。
2,实现
下面看看实现吧。
对于C#的Event的对象,我的研究的不深,只是知道怎么使用。
从我使用的角度看,我的理解C#中的Event就是一个delegate的集合对象,
在特定的时候调用所有delegate,完成事件的广播动作。
那什么是delegate?
我的理解就是对象化的函数指针。
那按照这个思路考虑的话,要用C++实现Event,
首先就要实现出类似delegate的东西,这个C++类似的就是Functor了,
对于Functor应该都不陌生了,我是参照这篇博文的设计实现的:
http://www.cppblog.com/kevinlynx/archive/2008/03/17/44678.html
有了Functor,Event不过就是一个Functor的集合的包装而已。
具体就不一一说明了,直接上代码,代码才是硬道理。
Functor.h和Event.h的代码如下:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | //=Functor.h======================================================================= // Created : 2009-10-08 // Description : template Functor class // Usage : #if 0 typedef Functor<void, void> FunctorVoid; typedef Functor<int, TYPE_LIST3(int, bool)> FunctorIntBool; FunctorVoid fnt1(&Print); fnt1(); FunctorIntBool fnt2(&func1); fnt2(12, true); FunctorIntBool fnt3(&a1, &A1::func); fnt3(12, true); #endif // //================================================================================= #pragma once struct null_type { }; template <typename _T, typename _U> struct type_list { typedef _T head_type; typedef _U tail_type; }; #define TYPE_LIST1( T1 ) type_list<T1, null_type> #define TYPE_LIST2( T1, T2 ) type_list<T1, TYPE_LIST1( T2 ) > #define TYPE_LIST3( T1, T2, T3 ) type_list<T1, TYPE_LIST2( T2, T3 ) > #define TYPE_LIST4( T1, T2, T3, T4 ) type_list<T1, TYPE_LIST3( T2, T3, T4 ) > #define TYPE_LIST5( T1, T2, T3, T4, T5 ) type_list<T1, TYPE_LIST4( T2, T3, T4, T5 ) > #define TYPE_LIST6( T1, T2, T3, T4, T5, T6 ) type_list<T1, TYPE_LIST5( T2, T3, T4, T5, T6 ) > template <typename _R> struct handler_type_base { typedef _R result_type; typedef null_type param1_type; typedef null_type param2_type; typedef null_type param3_type; typedef null_type param4_type; typedef null_type param5_type; typedef null_type param6_type; }; // // handler_base // template <typename _R, typename _ParamList> struct handler_base; // 0 param template <typename _R> struct handler_base<_R, void> : public handler_type_base<_R> { virtual _R operator() ( void ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // 1 param template <typename _R, typename _P1> struct handler_base<_R, TYPE_LIST1( _P1 ) > : public handler_type_base<_R> { typedef _P1 param1_type; virtual _R operator() ( _P1 ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // 2 param template <typename _R, typename _P1, typename _P2> struct handler_base<_R, TYPE_LIST2( _P1, _P2 ) > : public handler_type_base<_R> { typedef _P1 param1_type; typedef _P2 param2_type; virtual _R operator() ( _P1, _P2 ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // 3 param template <typename _R, typename _P1, typename _P2, typename _P3> struct handler_base<_R, TYPE_LIST3( _P1, _P2, _P3 ) > : public handler_type_base<_R> { typedef _P1 param1_type; typedef _P2 param2_type; typedef _P3 param3_type; virtual _R operator() ( _P1, _P2, _P3 ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // 4 param template <typename _R, typename _P1, typename _P2, typename _P3, typename _P4> struct handler_base<_R, TYPE_LIST4( _P1, _P2, _P3, _P4 ) > : public handler_type_base<_R> { typedef _P1 param1_type; typedef _P2 param2_type; typedef _P3 param3_type; typedef _P4 param4_type; virtual _R operator() ( _P1, _P2, _P3, _P4 ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // 5 param template <typename _R, typename _P1, typename _P2, typename _P3, typename _P4, typename _P5> struct handler_base<_R, TYPE_LIST5( _P1, _P2, _P3, _P4, _P5 ) > : public handler_type_base<_R> { typedef _P1 param1_type; typedef _P2 param2_type; typedef _P3 param3_type; typedef _P4 param4_type; typedef _P5 param5_type; virtual _R operator() ( _P1, _P2, _P3, _P4, _P5 ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // 6 param template <typename _R, typename _P1, typename _P2, typename _P3, typename _P4, typename _P5, typename _P6> struct handler_base<_R, TYPE_LIST6( _P1, _P2, _P3, _P4, _P5, _P6 ) > : public handler_type_base<_R> { typedef _P1 param1_type; typedef _P2 param2_type; typedef _P3 param3_type; typedef _P4 param4_type; typedef _P5 param5_type; typedef _P6 param6_type; virtual _R operator() ( _P1, _P2, _P3, _P4, _P5, _P6 ) = 0; virtual bool is_equal(handler_base*) = 0; virtual handler_base* clone() = 0; }; // // class handler // template <typename _R, typename _ParamList, typename _FuncType> class handler : public handler_base<_R, _ParamList> { public: typedef _FuncType func_type; typedef handler_base<_R, _ParamList> base_type; typedef typename base_type::param1_type param1_type; typedef typename base_type::param2_type param2_type; typedef typename base_type::param3_type param3_type; typedef typename base_type::param4_type param4_type; typedef typename base_type::param5_type param5_type; typedef typename base_type::param6_type param6_type; public: handler( const func_type &func ) : _func( func ) { } _R operator() () { return _func(); } _R operator() ( param1_type p ) { return _func( p ); } _R operator() ( param1_type p1, param2_type p2 ) { return _func( p1, p2 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3 ) { return _func( p1, p2, p3 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4 ) { return _func( p1, p2, p3, p4 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4, param5_type p5 ) { return _func( p1, p2, p3, p4, p5 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4, param5_type p5, param6_type p6 ) { return _func( p1, p2, p3, p4, p5, p6 ); } bool is_equal(base_type* r_value) { handler* p = (handler*)(r_value); if (_func != p->_func) { return false; } return true; } base_type* clone() { base_type* p = new handler(_func); return p; } private: func_type _func; }; // // class member_handler // template <typename _R, typename _ParamList, typename _FuncType, typename _ObjType> class member_handler : public handler_base<_R, _ParamList> { public: typedef _FuncType func_type; typedef _ObjType obj_type; typedef handler_base<_R, _ParamList> base_type; typedef typename base_type::param1_type param1_type; typedef typename base_type::param2_type param2_type; typedef typename base_type::param3_type param3_type; typedef typename base_type::param4_type param4_type; typedef typename base_type::param5_type param5_type; typedef typename base_type::param6_type param6_type; public: member_handler( obj_type *obj, const func_type &func ) : _obj( obj ), _func( func ) { } _R operator() () { return (_obj->*_func)(); } _R operator() ( param1_type p ) { return (_obj->*_func)( p ); } _R operator() ( param1_type p1, param2_type p2 ) { return (_obj->*_func)( p1, p2 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3 ) { return (_obj->*_func)( p1, p2, p3 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4 ) { return (_obj->*_func)( p1, p2, p3, p4 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4, param5_type p5 ) { return (_obj->*_func)( p1, p2, p3, p4, p5 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4, param5_type p5, param6_type p6 ) { return (_obj->*_func)( p1, p2, p3, p4, p5, p6 ); } bool is_equal(base_type* r_value) { member_handler* p = (member_handler*)(r_value); if (_obj != p->_obj) { return false; } if (_func != p->_func) { return false; } return true; } base_type* clone() { base_type* p = new member_handler(_obj, _func); return p; } private: obj_type *_obj; func_type _func; }; // // class Functor // template <typename _R, typename _ParamList> class Functor { public: typedef handler_base<_R, _ParamList> handler_type ; typedef typename handler_type::param1_type param1_type; typedef typename handler_type::param2_type param2_type; typedef typename handler_type::param3_type param3_type; typedef typename handler_type::param4_type param4_type; typedef typename handler_type::param5_type param5_type; typedef typename handler_type::param6_type param6_type; public: template <typename _FuncType> Functor( _FuncType func ) : _handler( new handler<_R, _ParamList, _FuncType>( func ) ) { } template <typename _ObjType, typename _FuncType> Functor( _ObjType *obj, _FuncType func ) : _handler( new member_handler<_R, _ParamList, _FuncType, _ObjType>( obj, func ) ) { } Functor( const Functor& f ) { _handler = f._handler->clone(); } ~Functor() { delete _handler; } _R operator() () { return (*_handler)(); } _R operator() ( param1_type p ) { return (*_handler)( p ); } _R operator() ( param1_type p1, param2_type p2 ) { return (*_handler)( p1, p2 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3 ) { return (*_handler)( p1, p2, p3 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4 ) { return (*_handler)( p1, p2, p3, p4 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4, param5_type p5 ) { return (*_handler)( p1, p2, p3, p4, p5 ); } _R operator() ( param1_type p1, param2_type p2, param3_type p3, param4_type p4, param5_type p5, param6_type p6 ) { return (*_handler)( p1, p2, p3, p4, p5, p6 ); } bool operator==(const Functor& r_value) { return _handler->is_equal(r_value._handler); } bool operator!=(const Functor& r_value) { return !_handler->is_equal(r_value._handler); } Functor& operator=(const Functor& r_value) { delete _handler; _handler = r_value._handler->clone(); return *this; } private: handler_type *_handler; }; |
下面是Event类的实现文件:Event.h
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | // Event.h #pragma once |