最近在做一個軍團系統的資料片開發,因為策劃提出了很多遍歷某一軍團當前所有在線玩家的操作(例如發公告、拉人、給獎勵),所以就想到了用回調。
脫離實際項目代碼,先看一下示例實現:
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() www.2cto.com
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 功能挺強大的,用它來實現回調和委托還是很方便的。