最近在做一個(gè)軍團(tuán)系統(tǒng)的資料片開發(fā),因?yàn)椴邉澨岢隽撕芏啾闅v某一軍團(tuán)當(dāng)前所有在線玩家的操作(例如發(fā)公告、拉人、給獎(jiǎng)勵(lì)),所以就想到了用回調(diào)。
脫離實(shí)際項(xiàng)目代碼,先看一下示例實(shí)現(xiàn):
1 /**
2 *\author peakflys
3 *\brief C方式實(shí)現(xiàn)的C++回調(diào)
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&);//成員函數(shù)
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 }
寫完之后編譯、運(yùn)行,一切okay,不過后來再看相應(yīng)代碼時(shí),越看越不順眼,尤其是類似于示例中的第57行:
(this->*fun)(*it); ,感覺使用很暴力,完全沒有OO的優(yōu)雅感,突然間想到了c++ TR1草案中的function和bind函數(shù)(c++11已經(jīng)將其轉(zhuǎn)正了)。
于是重新實(shí)現(xiàn)回調(diào)功能,示例代碼如下:
1 /**
2 *\author peakflys
3 *\brief C++方式實(shí)現(xiàn)的C++回調(diào)
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 }
本文使用的編譯環(huán)境是 gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46),c++11已經(jīng)把命名空間std::tr1下的函數(shù)賺到了std下。
這樣實(shí)現(xiàn),看起來就好很多了,可讀性也高了不少。新標(biāo)準(zhǔn)擴(kuò)展的function和bind 功能挺強(qiáng)大的,用它來實(shí)現(xiàn)回調(diào)和委托還是很方便的。