在C++中实现回调机制的几种方式一文中,我们提到了实现回调的三种方式(C风格的回调函数, Sink方式和Delegate方式)。在面向对象开发中,delegate的方式是最灵活和方便的,因此很早就有人用复杂的模板去模拟, 实现起来很复杂。但是现在借助C++11的function和bind, 我们可以很方便的去实现。下面是我自己的一种实现方式:
大概实现思想是我们通过一个内置的CEventHandler 类来封装处理函数,我们可以通过AddHandler来添加事件处理函数,添加时会返回一个Cookie,我们可以通过该Cookie来RemoveHandler, 下面是测试代码:
以下是测试结果:

可以看到, 我们在普通C函数, 类成员函数和仿函数(functor)中都测试通过。
另外对于事件函数返回值为void的情况,会编译出错,我们需要偏特化一下:
最后谈一下在写这个代码中遇到的问题:
(1)不知道你能不能发现下面代码的问题, 我在写代码时就栽在这里了:
1 vector<int*> v;
(2)我们想把cookei_type放到类里面去, 类似这样:
可发现要这样使用:
注:上面的代码还没有经过真正商业使用,如果有问题欢迎指出。
1 #pragma once
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
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, 下面是测试代码:
1 // EventTest.cpp : Defines the entry point for the console application.
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
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的情况,会编译出错,我们需要偏特化一下:
1 template< typename T1, typename T2>
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 };
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;
2 int* p1 = new int(1);
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());
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放到类里面去, 类似这样:
1 template<typename TR, typename T1, typename T2>
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;
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;
可发现要这样使用:
Common::CEvent<int, CObjectX*, CClickEventArgs&>::cookie_type c1 = btn.OnClicked.AddHandler(&obj, &CMyClass::OnBtuttonClicked);
太不方便了, 不知道大家有没有好的方法。注:上面的代码还没有经过真正商业使用,如果有问题欢迎指出。
在上文 在C++中实现事件(委托) 中我们实现的C#里委托方式的事件处理, 虽然使用很方便,但是感觉似乎少了一点C#的味道, 下面我们尝试把它改成真正的C#版。
其实要改成真正的C#版,我们主要要做2件事, 一是吧CEventHandler放到外面,可以让外部直接构造, 二是实现operator +=和operator -=, 下面是我的实现代码:
然后我们就可以这样使用了:
怎么样,是不是感觉和C#一样了 !
最后,我们比较一下2种实现方式:
第一种方法把委托函数类型封装起来了,对外部来说是透明的, 使用起来更简单。
第二种方式把委托函数的类型暴露了出来, 适用于事件处理函数类型各异,比较强调事件处理函数类型的场合。
其实对于C++来说,个人觉得还是第一种方式更合理, 不知道大家怎么看?
其实要改成真正的C#版,我们主要要做2件事, 一是吧CEventHandler放到外面,可以让外部直接构造, 二是实现operator +=和operator -=, 下面是我的实现代码:
#pragma once
#include <functional>
#include <algorithm>
#include <vector>
#include <assert.h>
namespace Common
{
typedef void* cookie_type;
template<typename TR, typename T1, typename T2>
class CEventHandler
{
public:
typedef TR return_type;
typedef T1 first_type;
typedef T2 second_type;
typedef std::function<return_type (first_type, second_type)> handler_type;
CEventHandler(const CEventHandler& h)
{
_handler = h._handler;
assert(_handler != nullptr);
}
CEventHandler(handler_type h)
{
_handler = h;
assert(_handler != nullptr);
}
template<typename class_type, typename class_fun>
CEventHandler(class_type* pThis, class_fun object_function)
{
using namespace std::placeholders;
_handler = std::bind(object_function, pThis, _1, _2);
assert(_handler != nullptr);
}
return_type operator()(first_type p1, second_type p2)
{
return_type ret = return_type();
assert(_handler != nullptr);
if(_handler != nullptr) ret = _handler(p1, p2);
return ret;
}
handler_type _handler;
};
template<typename EventHandler>
class CEvent
{
public:
typedef EventHandler event_handler_type;
typedef typename event_handler_type::return_type return_type;
typedef typename event_handler_type::first_type first_type;
typedef typename event_handler_type::second_type second_type;
typedef typename event_handler_type::handler_type handler_type;
~CEvent()
{
Clear();
}
return_type operator()(first_type p1, second_type p2)
{
return_type ret = return_type();
size_t size = _handlers.size();
for(auto p : _handlers)
{
ret = p->operator()(p1, p2);
}
return ret;
}
cookie_type AddHandler(const event_handler_type& h)
{
event_handler_type*p = new(nothrow) event_handler_type(h);
if(p != nullptr) _handlers.push_back(p);
return (cookie_type)p;
}
void RemoveHandler(cookie_type cookie)
{
event_handler_type* p = (event_handler_type*)cookie;
auto itr = std::find(_handlers.begin(), _handlers.end(), p);
if(itr != _handlers.end())
{
_handlers.erase(itr);
delete p;
}
else
{
assert(false);
}
}
cookie_type operator += (const event_handler_type& pHandler)
{
return AddHandler(pHandler);
}
void operator -= (cookie_type cookie)
{
RemoveHandler(cookie);
}
void Clear()
{
if(!_handlers.empty())
{
int n = _handlers.size();
std::for_each(_handlers.begin(), _handlers.end(), [](event_handler_type* p)
{
assert(p != nullptr);
delete p;
});
_handlers.clear();
}
}
private:
std::vector<event_handler_type*> _handlers;
};
} //Common
#include <functional>
#include <algorithm>
#include <vector>
#include <assert.h>
namespace Common
{
typedef void* cookie_type;
template<typename TR, typename T1, typename T2>
class CEventHandler
{
public:
typedef TR return_type;
typedef T1 first_type;
typedef T2 second_type;
typedef std::function<return_type (first_type, second_type)> handler_type;
CEventHandler(const CEventHandler& h)
{
_handler = h._handler;
assert(_handler != nullptr);
}
CEventHandler(handler_type h)
{
_handler = h;
assert(_handler != nullptr);
}
template<typename class_type, typename class_fun>
CEventHandler(class_type* pThis, class_fun object_function)
{
using namespace std::placeholders;
_handler = std::bind(object_function, pThis, _1, _2);
assert(_handler != nullptr);
}
return_type operator()(first_type p1, second_type p2)
{
return_type ret = return_type();
assert(_handler != nullptr);
if(_handler != nullptr) ret = _handler(p1, p2);
return ret;
}
handler_type _handler;
};
template<typename EventHandler>
class CEvent
{
public:
typedef EventHandler event_handler_type;
typedef typename event_handler_type::return_type return_type;
typedef typename event_handler_type::first_type first_type;
typedef typename event_handler_type::second_type second_type;
typedef typename event_handler_type::handler_type handler_type;
~CEvent()
{
Clear();
}
return_type operator()(first_type p1, second_type p2)
{
return_type ret = return_type();
size_t size = _handlers.size();
for(auto p : _handlers)
{
ret = p->operator()(p1, p2);
}
return ret;
}
cookie_type AddHandler(const event_handler_type& h)
{
event_handler_type*p = new(nothrow) event_handler_type(h);
if(p != nullptr) _handlers.push_back(p);
return (cookie_type)p;
}
void RemoveHandler(cookie_type cookie)
{
event_handler_type* p = (event_handler_type*)cookie;
auto itr = std::find(_handlers.begin(), _handlers.end(), p);
if(itr != _handlers.end())
{
_handlers.erase(itr);
delete p;
}
else
{
assert(false);
}
}
cookie_type operator += (const event_handler_type& pHandler)
{
return AddHandler(pHandler);
}
void operator -= (cookie_type cookie)
{
RemoveHandler(cookie);
}
void Clear()
{
if(!_handlers.empty())
{
int n = _handlers.size();
std::for_each(_handlers.begin(), _handlers.end(), [](event_handler_type* p)
{
assert(p != nullptr);
delete p;
});
_handlers.clear();
}
}
private:
std::vector<event_handler_type*> _handlers;
};
} //Common
然后我们就可以这样使用了:
// EventTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "event2.h"
using namespace std;
class CObjectX
{
};
class CClickEventArgs: public CObjectX
{
};
class CButton: public CObjectX
{
public:
void FireClick()
{
CClickEventArgs args;
OnClicked(this, args);
}
typedef Common::CEventHandler<int, CObjectX*, CClickEventArgs&> ButtonClickEventHandler;
Common::CEvent<ButtonClickEventHandler> OnClicked;
};
class CMyClass
{
public:
int OnBtuttonClicked(CObjectX* pButton, CClickEventArgs& args)
{
cout << "CMyClass: Receive button clicked event" << endl;
return 1;
}
};
int OnBtuttonClicked_C_fun(CObjectX* pButton, CClickEventArgs& args)
{
cout << "C Style Function: Receive button clicked event" << endl;
return 1;
}
class CMyFunObj
{
public:
int operator()(CObjectX* pButton, CClickEventArgs& args)
{
cout << "Functor: Receive button clicked event" << endl;
return 1;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CButton btn;
CMyClass obj;
Common::cookie_type c1 = btn.OnClicked += CButton::ButtonClickEventHandler(&obj, &CMyClass::OnBtuttonClicked);
Common::cookie_type c2 = btn.OnClicked += CButton::ButtonClickEventHandler(OnBtuttonClicked_C_fun);
CMyFunObj functor;
Common::cookie_type c3 = btn.OnClicked += CButton::ButtonClickEventHandler(functor);
btn.FireClick();
btn.OnClicked -= c2;
std::cout << endl;
btn.FireClick();
system("pause");
return 0;
}
//
#include "stdafx.h"
#include <iostream>
#include "event2.h"
using namespace std;
class CObjectX
{
};
class CClickEventArgs: public CObjectX
{
};
class CButton: public CObjectX
{
public:
void FireClick()
{
CClickEventArgs args;
OnClicked(this, args);
}
typedef Common::CEventHandler<int, CObjectX*, CClickEventArgs&> ButtonClickEventHandler;
Common::CEvent<ButtonClickEventHandler> OnClicked;
};
class CMyClass
{
public:
int OnBtuttonClicked(CObjectX* pButton, CClickEventArgs& args)
{
cout << "CMyClass: Receive button clicked event" << endl;
return 1;
}
};
int OnBtuttonClicked_C_fun(CObjectX* pButton, CClickEventArgs& args)
{
cout << "C Style Function: Receive button clicked event" << endl;
return 1;
}
class CMyFunObj
{
public:
int operator()(CObjectX* pButton, CClickEventArgs& args)
{
cout << "Functor: Receive button clicked event" << endl;
return 1;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CButton btn;
CMyClass obj;
Common::cookie_type c1 = btn.OnClicked += CButton::ButtonClickEventHandler(&obj, &CMyClass::OnBtuttonClicked);
Common::cookie_type c2 = btn.OnClicked += CButton::ButtonClickEventHandler(OnBtuttonClicked_C_fun);
CMyFunObj functor;
Common::cookie_type c3 = btn.OnClicked += CButton::ButtonClickEventHandler(functor);
btn.FireClick();
btn.OnClicked -= c2;
std::cout << endl;
btn.FireClick();
system("pause");
return 0;
}
怎么样,是不是感觉和C#一样了 !
最后,我们比较一下2种实现方式:
第一种方法把委托函数类型封装起来了,对外部来说是透明的, 使用起来更简单。
第二种方式把委托函数的类型暴露了出来, 适用于事件处理函数类型各异,比较强调事件处理函数类型的场合。
其实对于C++来说,个人觉得还是第一种方式更合理, 不知道大家怎么看?
分类: C++