最近在做一个军团系统的资料片开发,因为策划提出了很多遍历某一军团当前所有在线玩家的操作(例如发公告、拉人、给奖励),所以就想到了用回调。
脱离实际项目代码,先看一下示例实现:
1 /**
2 *\author peakflys
3 *\brief C方式实现的C++回调
4 */
5 #include <iostream>
6 #include <vector>
7
8 #define COUNTARRAY(a) sizeof(a)/sizeof(a[0])
9
10 class User
11 {
12 public:
13 User(std::string _name,bool _online) : name(_name),online(_online)
14 {
15 }
16 const std::string& getName() const
17 {
18 return this->name;
19 }
20 bool checkOnLine()
21 {
22 return online;
23 }
24 private:
25 std::string name;
26 bool online;
27 };
28
29 class Test;
30 typedef void(Test::*pFun)(const User&);//成员函数
31
32 class Test
33 {
34 public:
35 Test(const std::vector<User>& _userList) : userList(_userList)
36 {
37 }
38
39 void print(const User& user);
40
41 void execEvery(pFun fun);
42
43 private:
44 std::vector<User> userList;
45 };
46
47 void Test::print(const User& user)
48 {
49 std::cout<<user.getName()<<" ";
50 }
51
52 void Test::execEvery(pFun fun)
53 {
54 for(std::vector<User>::iterator it=userList.begin();it!=userList.end();++it)
55 {
56 if((*it).checkOnLine())
57 (this->*fun)(*it); //注意格式
58 }
59 std::cout<<std::endl;
60 }
61
62 int main()
63 {
64 User um[] = {User("张三",true),User("李四",false),User("王二",true),User("麻子",true)};
65 std::vector<User> vu(um,um+COUNTARRAY(um));
66 Test t(vu);
67 t.execEvery(&Test::print);
68 return 0;
69 }
写完之后编译、运行,一切okay,不过后来再看相应代码时,越看越不顺眼,尤其是类似于示例中的第57行:
(this->*fun)(*it); ,感觉使用很暴力,完全没有OO的优雅感,突然间想到了c++ TR1草案中的function和bind函数(c++11已经将其转正了)。
于是重新实现回调功能,示例代码如下:
1 /**
2 *\author peakflys
3 *\brief C++方式实现的C++回调
4 */
5 #include <iostream>
6 #include <vector>
7 #include <tr1/functional>
8
9 #define COUNTARRAY(a) sizeof(a)/sizeof(a[0])
10
11 class User
12 {
13 public:
14 User(std::string _name,bool _online) : name(_name),online(_online)
15 {
16 }
17 const std::string& getName() const
18 {
19 return this->name;
20 }
21 bool checkOnLine()
22 {
23 return online;
24 }
25 private:
26 std::string name;
27 bool online;
28 };
29
30 class Test
31 {
32 public:
33 Test(const std::vector<User>& _userList) : userList(_userList)
34 {
35 }
36
37 void static print(const User& user);
38
39 void execEvery(std::tr1::function<void (const User&)> func);
40 private:
41 std::vector<User> userList;
42 };
43
44 void Test::print(const User& user)
45 {
46 std::cout<<user.getName()<<" ";
47 }
48
49 void Test::execEvery(std::tr1::function<void (const User&)> func)
50 {
51 for(std::vector<User>::iterator it=userList.begin();it!=userList.end();++it)
52 {
53 if((*it).checkOnLine())
54 func(*it); //注意格式
55 }
56 std::cout<<std::endl;
57 }
58
59 int main()
60 {
61 User um[] = {User("张三",true),User("李四",false),User("王二",true),User("麻子",true)};
62 std::vector<User> vu(um,um+COUNTARRAY(um));
63 Test t(vu);
64 t.execEvery(std::tr1::bind(Test::print,std::tr1::placeholders::_1));
65 return 0;
66 }
本文使用的编译环境是 gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46),c++11已经把命名空间std::tr1下的函数赚到了std下。
这样实现,看起来就好很多了,可读性也高了不少。新标准扩展的function和bind 功能挺强大的,用它来实现回调和委托还是很方便的。