在之前的博文中, 我们探讨过映射的重要作用, 请直接看:http://blog.csdn.net/stpeace/article/details/39452203, 在那篇文章中, 我们是用STL中的map来做的, map建立的是key-value映射, 在本文中, 我们自己来建立映射, 并讨论一个更为复杂的程序, 顺便再次复习一下注册与回调。
注册与回调? 有那么复杂么?没有必要过多地扯了, 直接上代码:
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 // 前向声明
6 class BasicMod;
7
8
9 //类函数指针类型
10 typedef void (BasicMod:: *PFun)(const char* pParaName);
11
12
13 // 映射结点
14 typedef struct
15 {
16 BasicMod *pMod;
17 char szParaName[1024];
18 PFun operTypeOne;
19 PFun operTypeTwo;
20 PFun operTypeThree;
21 }MyMap;
22
23
24 // 用全局的g_pv保存结点指针
25 vector<MyMap *> g_pv;
26
27
28 // 执行类, 提供注册, 查找接口, 并执行回调操作
29 class Do
30 {
31 public:
32 // 单例
33 static Do *getInstance()
34 {
35 static Do *p = NULL;
36 if(NULL == p)
37 {
38 p = new Do;
39 }
40
41 return p;
42 }
43
44 // 注册接口
45 void regNode(BasicMod *pb, MyMap *pmap, int i)
46 {
47 MyMap *p = new MyMap;
48 p->pMod = pb;
49 memset(p->szParaName, 0, sizeof(p->szParaName));
50 strncpy(p->szParaName, (pmap + i)->szParaName, sizeof(p->szParaName) - 1);
51 p->operTypeOne = (pmap + i)->operTypeOne;
52 p->operTypeTwo = (pmap + i)->operTypeTwo;
53 p->operTypeThree = (pmap + i)->operTypeThree;
54
55 g_pv.push_back(p);
56 }
57
58 // 查找接口
59 MyMap *findNode(const char *pParaName)
60 {
61 int n = g_pv.size();
62 int i = 0;
63 for(i = 0; i < n; i++)
64 {
65 if(0 == strcmp(g_pv[i]->szParaName, pParaName))
66 {
67 return g_pv[i];
68 }
69 }
70
71 return NULL;
72 }
73
74 // 执行回调操作
75 void exect(const char *pParaName)
76 {
77 MyMap *p = findNode(pParaName);
78 if(NULL != p && NULL != p->pMod)
79 {
80 ((p->pMod)->*(p->operTypeOne))(pParaName);
81 ((p->pMod)->*(p->operTypeTwo))(pParaName);
82 ((p->pMod)->*(p->operTypeThree))(pParaName);
83 }
84 }
85 };
86
87
88 // 基类
89 class BasicMod
90 {
91 public:
92 void reg(BasicMod *pm, MyMap *p, int i)
93 {
94 Do::getInstance()->regNode(pm, p, i);
95 }
96 };
97
98
99 // 格式化
100 #define TOGETHER(mod, name, f1, f2, f3) {NULL, name, (PFun)(&mod::f1), (PFun)(&mod::f2), (PFun)(&mod::f3)}
101
102
103 // 模块1
104 class Mod1 : public BasicMod
105 {
106 public:
107 static Mod1* getInstance()
108 {
109 static Mod1* p = NULL;
110 if(NULL == p)
111 {
112 p = new Mod1;
113 }
114
115 return p;
116 }
117
118 // 模块1的初始化
119 void init()
120 {
121 MyMap mapArr[] =
122 {
123 TOGETHER(Mod1, "cpu", fun1Cpu, fun2Cpu, fun3Cpu),
124 };
125
126 int n = sizeof(mapArr) / sizeof(mapArr[0]);
127 int i = 0;
128 for(i = 0; i < n; i++)
129 {
130 // 注册
131 reg(getInstance(), mapArr, i);
132 }
133 }
134
135 // 提供回调接口
136 void fun1Cpu(const char *pParaName)
137 {
138 cout << "mod1, pParaName is " << pParaName << endl;
139 }
140
141 // 提供回调接口
142 void fun2Cpu(const char *pParaName)
143 {
144 cout << "mod1, pParaName is " << pParaName << endl;
145 }
146
147 // 提供回调接口
148 void fun3Cpu(const char *pParaName)
149 {
150 cout << "mod1, pParaName is " << pParaName << endl;
151 }
152 };
153
154
155 class Mod2 : public BasicMod
156 {
157 public:
158 static Mod2* getInstance()
159 {
160 static Mod2* p = NULL;
161 if(NULL == p)
162 {
163 p = new Mod2;
164 }
165
166 return p;
167 }
168
169 void init()
170 {
171 MyMap mapArr[] =
172 {
173 TOGETHER(Mod2, "flash", fun1Flash, fun2Flash, fun3Flash),
174 };
175
176 int n = sizeof(mapArr) / sizeof(mapArr[0]);
177 int i = 0;
178 for(i = 0; i < n; i++)
179 {
180 reg(getInstance(), mapArr, i);
181 }
182 }
183
184 void fun1Flash(const char *pParaName)
185 {
186 cout << "mod2, pParaName is " << pParaName << endl;
187 }
188
189 void fun2Flash(const char *pParaName)
190 {
191 cout << "mod2, pParaName is " << pParaName << endl;
192 }
193
194 void fun3Flash(const char *pParaName)
195 {
196 cout << "mod2, pParaName is " << pParaName << endl;
197 }
198 };
199
200
201 int main()
202 {
203 // 模块初始化
204 Mod1::getInstance()->init();
205 Mod2::getInstance()->init();
206
207 // 执行操作
208 Do::getInstance()->exect("cpu");
209 Do::getInstance()->exect("flash");
210 Do::getInstance()->exect("mem");
211
212 return 0;
213 }
程序的结果为:
mod1, pParaName is cpu
mod1, pParaName is cpu
mod1, pParaName is cpu
mod2, pParaName is flash
mod2, pParaName is flash
mod2, pParaName is flash
我们也可以对上述程序作一下等价变换, 得到:
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 // 前向声明
6 class BasicMod;
7
8
9 //类函数指针类型
10 typedef void (BasicMod:: *PFun)(const char* pParaName);
11
12
13 // 映射结点
14 typedef struct
15 {
16 BasicMod *pMod;
17 char szParaName[1024];
18 PFun operTypeOne;
19 PFun operTypeTwo;
20 PFun operTypeThree;
21 }MyMap;
22
23
24 // 用全局的g_pv保存结点指针
25 vector<MyMap *> g_pv;
26
27
28 // 执行类, 提供注册, 查找接口, 并执行回调操作
29 class Do
30 {
31 public:
32 // 单例
33 static Do *getInstance()
34 {
35 static Do *p = NULL;
36 if(NULL == p)
37 {
38 p = new Do;
39 }
40
41 return p;
42 }
43
44 // 注册接口
45 void regNode(BasicMod *pm, const char *pParaName, PFun one, PFun two, PFun three)
46 {
47 MyMap *p = new MyMap;
48 p->pMod = pm;
49 memset(p->szParaName, 0, sizeof(p->szParaName));
50 strncpy(p->szParaName, pParaName, sizeof(p->szParaName) - 1);
51 p->operTypeOne = one;
52 p->operTypeTwo = two;
53 p->operTypeThree = three;
54
55 g_pv.push_back(p);
56 }
57
58 // 查找接口
59 MyMap *findNode(const char *pParaName)
60 {
61 int n = g_pv.size();
62 int i = 0;
63 for(i = 0; i < n; i++)
64 {
65 if(0 == strcmp(g_pv[i]->szParaName, pParaName))
66 {
67 return g_pv[i];
68 }
69 }
70
71 return NULL;
72 }
73
74 // 执行回调操作
75 void exect(const char *pParaName)
76 {
77 MyMap *p = findNode(pParaName);
78 if(NULL != p && NULL != p->pMod)
79 {
80 ((p->pMod)->*(p->operTypeOne))(pParaName);
81 ((p->pMod)->*(p->operTypeTwo))(pParaName);
82 ((p->pMod)->*(p->operTypeThree))(pParaName);
83 }
84 }
85 };
86
87
88 // 基类
89 class BasicMod
90 {
91 public:
92 void reg(const char *pParaName, PFun one, PFun two, PFun three)
93 {
94 Do::getInstance()->regNode(this, pParaName, one, two, three);
95 }
96 };
97
98
99 // 格式化
100 #define TOGETHER(mod, name, f1, f2, f3) {NULL, name, (PFun)(&mod::f1), (PFun)(&mod::f2), (PFun)(&mod::f3)}
101
102
103 // 模块1
104 class Mod1 : public BasicMod
105 {
106 public:
107 static Mod1* getInstance()
108 {
109 static Mod1* p = NULL;
110 if(NULL == p)
111 {
112 p = new Mod1;
113 }
114
115 return p;
116 }
117
118 // 模块1的初始化
119 void init()
120 {
121 MyMap mapArr[] =
122 {
123 TOGETHER(Mod1, "cpu", fun1Cpu, fun2Cpu, fun3Cpu),
124 };
125
126 int n = sizeof(mapArr) / sizeof(mapArr[0]);
127 int i = 0;
128 for(i = 0; i < n; i++)
129 {
130 // 注册
131 reg(mapArr[i].szParaName, mapArr[i].operTypeOne, mapArr[i].operTypeTwo, mapArr[i].operTypeThree);
132 }
133 }
134
135 // 提供回调接口
136 void fun1Cpu(const char *pParaName)
137 {
138 cout << "mod1, pParaName is " << pParaName << endl;
139 }
140
141 // 提供回调接口
142 void fun2Cpu(const char *pParaName)
143 {
144 cout << "mod1, pParaName is " << pParaName << endl;
145 }
146
147 // 提供回调接口
148 void fun3Cpu(const char *pParaName)
149 {
150 cout << "mod1, pParaName is " << pParaName << endl;
151 }
152 };
153
154
155 class Mod2 : public BasicMod
156 {
157 public:
158 static Mod2* getInstance()
159 {
160 static Mod2* p = NULL;
161 if(NULL == p)
162 {
163 p = new Mod2;
164 }
165
166 return p;
167 }
168
169 void init()
170 {
171 MyMap mapArr[] =
172 {
173 TOGETHER(Mod2, "flash", fun1Flash, fun2Flash, fun3Flash),
174 };
175
176 int n = sizeof(mapArr) / sizeof(mapArr[0]);
177 int i = 0;
178 for(i = 0; i < n; i++)
179 {
180 reg(mapArr[i].szParaName, mapArr[i].operTypeOne, mapArr[i].operTypeTwo, mapArr[i].operTypeThree);
181 }
182 }
183
184 void fun1Flash(const char *pParaName)
185 {
186 cout << "mod2, pParaName is " << pParaName << endl;
187 }
188
189 void fun2Flash(const char *pParaName)
190 {
191 cout << "mod2, pParaName is " << pParaName << endl;
192 }
193
194 void fun3Flash(const char *pParaName)
195 {
196 cout << "mod2, pParaName is " << pParaName << endl;
197 }
198 };
199
200
201 int main()
202 {
203 // 模块初始化
204 Mod1::getInstance()->init();
205 Mod2::getInstance()->init();
206
207 // 执行操作
208 Do::getInstance()->exect("cpu");
209 Do::getInstance()->exect("flash");
210 Do::getInstance()->exect("mem");
211
212 return 0;
213 }
我们看到, 上述程序建立了一个name对于{f1, f2, f3}的映射, 适用范围更广。
而且, 以后如果再加字段, 程序猿只需要注意三处即可: 1. 增加initialize函数中数组中的项(增加映射);2. 在类中实现回调接口(增加回调接口); 3.在main中启动调用(启动执行)。
当然啦, 如果要增加模块3, 那也是很easy的。
反思一下:我突然发现, 我把上面的程序写复杂了, 其实, 也可以用STL map建立name到f1, f2, f3的映射, 此时, 要把{f1, f2, f3}看成一个整体, 上述程序用STL map进行改造后, 会更好, 有兴趣的朋友可以试试。 我相信: 一次刻骨铭心的体验胜过千百次说教。