2
3 #include <functional>
4 #include <algorithm>
5 #include <vector>
6 #include <assert.h>
7
8 namespace Common
9 {
10 typedef void* cookie_type;
11
12 template<typename TR, typename T1, typename T2>
13 class CEvent
14 {
15 public:
16 typedef TR return_type;
17 typedef T1 first_type;
18 typedef T2 second_type;
19
20 typedef std::function<return_type (first_type, second_type)> handler_type;
21
22 ~CEvent()
23 {
24 Clear();
25 }
26
27 return_type operator()(first_type p1, second_type p2)
28 {
29 return_type ret = return_type();
30 size_t size = _handlers.size();
31 for(size_t i=0; i<size; ++i)
32 {
33 ret = _handlers[i]->operator()(p1, p2);
34 }
35 return ret;
36 }
37
38 cookie_type AddHandler(std::function<return_type (first_type, second_type)> h)
39 {
40 CEventHandler*p = new(nothrow) CEventHandler(h);
41 if(p != nullptr) _handlers.push_back(p);
42 return (cookie_type)p;
43 }
44
45 template<typename class_type, typename class_fun>
46 cookie_type AddHandler(class_type* pThis, class_fun f)
47 {
48 CEventHandler* p = new(nothrow) CEventHandler(pThis, f);
49 if(p != nullptr) _handlers.push_back(p);
50 return (cookie_type)p;
51 }
52
53 void RemoveHandler(cookie_type cookie)
54 {
55 CEventHandler* p = (CEventHandler*)cookie;
56
57 auto itr = std::find(_handlers.begin(), _handlers.end(), p);
58 if(itr != _handlers.end())
59 {
60 _handlers.erase(itr);
61 delete p;
62 }
63 else
64 {
65 assert(false);
66 }
67 }
68
69 void Clear()
70 {
71 if(!_handlers.empty())
72 {
73 int n = _handlers.size();
74 std::for_each(_handlers.begin(), _handlers.end(), [](CEventHandler* p)
75 {
76 assert(p != nullptr);
77 delete p;
78 });
79 _handlers.clear();
80 }
81 }
82
83 private:
84 class CEventHandler
85 {
86 public:
87 CEventHandler(handler_type h)
88 {
89 _handler = h;
90 assert(_handler != nullptr);
91 }
92
93 template<typename class_type, typename class_fun>
94 CEventHandler(class_type* pThis, class_fun object_function)
95 {
96 using namespace std::placeholders;
97 _handler = std::bind(object_function, pThis, _1, _2);
98 assert(_handler != nullptr);
99 }
100
101 return_type operator()(first_type p1, second_type p2)
102 {
103 return_type ret = return_type();
104 assert(_handler != nullptr);
105 if(_handler != nullptr) ret = _handler(p1, p2);
106 return ret;
107 }
108
109 handler_type _handler;
110 };
111
112
113 private:
114 std::vector<CEventHandler*> _handlers;
115 };
116
117 } //Common
大概实现思想是我们通过一个内置的CEventHandler 类来封装处理函数,我们可以通过AddHandler来添加事件处理函数,添加时会返回一个Cookie,我们可以通过该Cookie来RemoveHandler, 下面是测试代码:
2 //
3
4 #include "stdafx.h"
5
6 #include <iostream>
7 #include "event1.h"
8
9 using namespace std;
10
11 class CObjectX
12 {
13
14 };
15
16 class CClickEventArgs: public CObjectX
17 {
18
19 };
20
21
22 class CButton: public CObjectX
23 {
24 public:
25 void FireClick()
26 {
27 CClickEventArgs args;
28 OnClicked(this, args);
29 }
30
31 Common::CEvent<int, CObjectX*, CClickEventArgs&> OnClicked;
32 };
33
34
35 class CMyClass
36 {
37 public:
38 int OnBtuttonClicked(CObjectX* pButton, CClickEventArgs& args)
39 {
40 cout << "CMyClass: Receive button clicked event" << endl;
41 return 1;
42 }
43 };
44
45 int OnBtuttonClicked_C_fun(CObjectX* pButton, CClickEventArgs& args)
46 {
47 cout << "C Style Function: Receive button clicked event" << endl;
48 return 1;
49 }
50
51
52 class CMyFunObj
53 {
54 public:
55 int operator()(CObjectX* pButton, CClickEventArgs& args)
56 {
57 cout << "Functor: Receive button clicked event" << endl;
58 return 1;
59 }
60 };
61
62 int _tmain(int argc, _TCHAR* argv[])
63 {
64 using namespace std::placeholders;
65
66 CButton btn;
67
68 CMyClass obj;
69 Common::cookie_type c1 = btn.OnClicked.AddHandler(&obj, &CMyClass::OnBtuttonClicked);
70
71 Common::cookie_type c2 = btn.OnClicked.AddHandler(OnBtuttonClicked_C_fun);
72
73 CMyFunObj functor;
74 Common::cookie_type c3 = btn.OnClicked.AddHandler(functor);
75
76 btn.FireClick();
77
78
79 btn.OnClicked.RemoveHandler(c2);
80
81 std::cout << endl;
82
83
84 btn.FireClick();
85
86 system("pause");
87
88 return 0;
89 }
90
以下是测试结果:

可以看到, 我们在普通C函数, 类成员函数和仿函数(functor)中都测试通过。
另外对于事件函数返回值为void的情况,会编译出错,我们需要偏特化一下:
2 class CEvent<void, T1, T2>
3 {
4 public:
5 typedef void return_type;
6 typedef T1 first_type;
7 typedef T2 second_type;
8
9 typedef std::function<return_type (first_type, second_type)> handler_type;
10
11 ~CEvent()
12 {
13 Clear();
14 }
15
16 return_type operator()(first_type p1, second_type p2)
17 {
18 size_t size = _handlers.size();
19 for(size_t i=0; i<size; ++i)
20 {
21 _handlers[i]->operator()(p1, p2);
22 }
23 }
24
25 cookie_type AddHandler(std::function<return_type (first_type, second_type)> h)
26 {
27 CEventHandler*p = new(nothrow) CEventHandler(h);
28 if(p != nullptr) _handlers.push_back(p);
29 return (cookie_type)p;
30 }
31
32 template<typename class_type, typename class_fun>
33 cookie_type AddHandler(class_type* pThis, class_fun f)
34 {
35 CEventHandler* p = new(nothrow) CEventHandler(pThis, f);
36 if(p != nullptr) _handlers.push_back(p);
37 return (cookie_type)p;
38 }
39
40 void RemoveHandler(cookie_type cookie)
41 {
42 CEventHandler* p = (CEventHandler*)cookie;
43
44 auto itr = std::find(_handlers.begin(), _handlers.end(), p);
45 if(itr != _handlers.end())
46 {
47 _handlers.erase(itr);
48 delete p;
49 }
50 else
51 {
52 assert(false);
53 }
54 }
55
56 void Clear()
57 {
58 if(!_handlers.empty())
59 {
60 int n = _handlers.size();
61 std::for_each(_handlers.begin(), _handlers.end(), [](CEventHandler* p)
62 {
63 assert(p != nullptr);
64 delete p;
65 });
66 _handlers.clear();
67 }
68 }
69
70 private:
71 class CEventHandler
72 {
73 public:
74 CEventHandler(handler_type h)
75 {
76 _handler = h;
77 assert(_handler != nullptr);
78 }
79
80 template<typename class_type, typename class_fun>
81 CEventHandler(class_type* pThis, class_fun object_function)
82 {
83 using namespace std::placeholders;
84 _handler = std::bind(object_function, pThis, _1, _2);
85 assert(_handler != nullptr);
86 }
87
88 return_type operator()(first_type p1, second_type p2)
89 {
90 assert(_handler != nullptr);
91 if(_handler != nullptr) _handler(p1, p2);
92 }
93
94 handler_type _handler;
95 };
96
97
98 private:
99 std::vector<CEventHandler*> _handlers;
100 };
最后谈一下在写这个代码中遇到的问题:
(1)不知道你能不能发现下面代码的问题, 我在写代码时就栽在这里了:
1 vector<int*> v;
3 v.push_back(p1);
4 int* p2 = new int(2);
5 v.push_back(p2);
6
7 //尝试删除所有值为p1的项
8 auto itr = remove(v.begin(), v.end(), p1);
9 for_each(itr, v.end(), [](int* p){delete p;});
10 v.erase(itr, v.end());
(2)我们想把cookei_type放到类里面去, 类似这样:
2 class CEvent
3 {
4 public:
5 typedef TR return_type;
6 typedef T1 first_type;
7 typedef T2 second_type;
8 typedef void* cookie_type;
可发现要这样使用:
注:上面的代码还没有经过真正商业使用,如果有问题欢迎指出。