注册与回调

C++ 再谈谈注册(本质是建立映射)与回调

  在之前的博文中, 我们探讨过映射的重要作用, 请直接看: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 struct15 {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 Do30 {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 BasicMod90 {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 struct15 {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 Do30 {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 BasicMod90 {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进行改造后, 会更好, 有兴趣的朋友可以试试。 我相信: 一次刻骨铭心的体验胜过千百次说教。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/228030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rk3568 RGMII KSZ8795 MAC TO MAC

RK3568与KSZ8795交换机芯片连接&#xff0c;直接MAC TO MAC方式&#xff0c;这样一下就扩展会4路网口&#xff0c;应该场合比较多&#xff0c;移植过程如下&#xff1a; 参考《Rockchip_Developer_Guide_Linux_MAC_TO_MAC_CN.pdf》 《rockchip RGMIImv88e6390 管理型交换机功…

【Spring】之Ioc和Aop快速了解

这里写目录标题 1.Spring框架是什么&#xff1f;简介&#xff1a;总结&#xff1a;Spring框架&#xff0c;可以理解为是一个管理者&#xff1a;管理整个分层架构&#xff08;MVC&#xff09;中的每一个对象&#xff1b;&#xff08;每一个对象称之为bean&#xff09; 2.Spring框…

太空旅行:计算机技术的崭新航程

太空旅行&#xff1a;计算机技术的崭新航程 一、引言 自古以来&#xff0c;人类就对浩渺的宇宙充满了无尽的好奇和渴望。随着科技的飞速发展&#xff0c;太空旅行已经从科幻小说中的构想变为现实。在这个过程中&#xff0c;计算机技术起到了不可或缺的作用。从阿波罗时代的初…

​FL Studio2024最新版本好不好用?有哪些新功能

FL Studio2024版是一款在国内非常受欢迎的多功能音频处理软件&#xff0c;我们可以通过这款软件来对多种不同格式的音频文件来进行编辑处理。而且FL Studio 2024版还为用户们准备了超多的音乐乐器伴奏&#xff0c;我们可以直接一键调取自己需要的音调。 FL Studio 2024版不仅拥…

HarmonyOS4.0从零开始的开发教程15HTTP数据请求

HarmonyOS&#xff08;十三&#xff09;HTTP数据请求 1 概述 日常生活中我们使用应用程序看新闻、发送消息等&#xff0c;都需要连接到互联网&#xff0c;从服务端获取数据。例如&#xff0c;新闻应用可以从新闻服务器中获取最新的热点新闻&#xff0c;从而给用户打造更加丰富…

MySQL进阶2 - 索引

MySQL进阶1 - 索引 1. 索引概述2. 索引结构2.1 二叉树2.2 B-Tree(多路平衡查找树)2.3 BTree2.4 Hash 3. 索引分类4. 索引语法5. SQL性能分析5.1 SQL执行频率5.2 慢查询日志5.3 profile5.4 explain执行计划5.3.1 EXPLAIN执行计划各字段含义&#xff1a; 6. 索引使…

SpringBoot+FastJson 优雅的过滤 Response Body

Spring 源码系列 1、Spring 学习之扩展点总结之后置处理器&#xff08;一&#xff09; 2、Spring 学习之扩展点总结之后置处理器&#xff08;二&#xff09; 3、Spring 学习之扩展点总结之自定义事件&#xff08;三&#xff09; 4、Spring 学习之扩展点总结之内置事件&#xf…

手把手教你Linux查找Java的安装目录并设置环境变量以及Linux下执行javac未找到命令的保姆级教学

查找Java的安装目录 输入 java -version&#xff0c;查看是否成功安装Java 输入 which java&#xff0c;查看Java的执行路径 输入 ls -lrt /usr/bin/java 输入 ls -lrt /etc/alternatives/java&#xff0c;/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64 就是J…

自动化测试(终章)webdriver的常用api(2)以及新的开始

目录 多层框架/窗口定位 多层框架的定位 frame是什么&#xff1f; 多层窗口定位 层级定位 使用 XPath 进行层级定位&#xff1a; 使用 CSS 选择器进行层级定位&#xff1a; 下拉框处理 alert、confirm、prompt 的处理 Alert 弹窗&#xff1a; Confirm 弹窗&#xff…

IDEA安装插件搜索不到插件的解决方法

解决idea安装所需插件&#xff0c;插件搜索不到的问题 1.通过设置代理和去掉使用安装链接的方式来解决的 File–>Settings–>Appearance & Behavior–>System Settings—>HTTP Proxy(修改为图片所示) 2.在系统设置中将更新选项中的“use secure connection”…

Xml与Json格式在线转换器

具体请前往&#xff1a;在线Json转Form表单参数工具

C语言之函数式宏

目录 函数和数据类型 函数式宏 函数和函数式宏 函数式宏和对象式宏 不带参数的函数式宏 函数式宏和逗号运算符 函数式宏和函数类似并且比函数更加灵活&#xff0c;下面我们就来学习函数式宏的相关内容。 函数和数据类型 我们来编写一个程序&#xff0c;它能计算出所读取…

Jetpack Compose开发一个Android WiFi导航应用

在以前的一篇文章构建一个WIFI室内定位系统_wifi定位系统-CSDN博客中&#xff0c;我介绍了如何用Android来测量WiFi信号&#xff0c;上传到服务器进行分析后&#xff0c;生成室内不同地方的WiFi指纹&#xff0c;从而帮助进行室内导航。当时我是用的HTML5的技术来快速开发一个An…

QQ邮箱发送工具类的实现

我们在日常开发中&#xff0c;需要实现一个对邮箱的发送&#xff0c;今天就实现邮箱的发送工具类&#xff0c;只需要一些注册邮箱之后的配置即可&#xff0c;我这边使用的是qq邮箱 0.加上依赖 <!--邮箱--><dependency><groupId>org.springframework.boot&l…

基于vue开发 - 编写登录页面样式

vue创建项目&#xff0c;使用可视化界面安装插件-CSDN博客 使用vue UI安装路由插件-CSDN博客 基于vue开发-创建登录页-CSDN博客 在src/views文件夹中创建登录页面login.vue&#xff0c;在router/index.js文件中加入登录页的路由&#xff0c;然后在浏览器中输入登录页的路径就…

FL Studio终身永久2024中文版下载安装详细操作图文步骤教程

FL Studio2024版是一款在国内非常受欢迎的多功能音频处理软件&#xff0c;我们可以通过这款软件来对多种不同格式的音频文件来进行编辑处理。而且FL Studio 2024版还为用户们准备了超多的音乐乐器伴奏&#xff0c;我们可以直接一键调取自己需要的音调。 FL Studio 2024版不仅拥…

算法设计基础——综合

算法设计基础中最基础的几种算法&#xff1a;分治法、减治法、贪心法、动态规划法、回溯法基本都掌握后&#xff0c;我们现在可以对这些算法做整体的比较&#xff0c;本次实验使用蛮力法、动态规划法、回溯法来求解0/1背包问题&#xff0c;来比较各个算法的优劣。 1. 蛮力法 …

代码随想录27期|Python|Day16|二叉树|104.二叉树的最大深度|111.二叉树的最小深度|222.完全二叉树的节点个数

二叉树专题&#xff0c;重点掌握后续的递归和中间节点的处理。 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 本题在前一章已经解决了层序遍历的解法&#xff0c;现在来聊一下递归法。 首先需要明确两个概念&#xff1a;深度和高度。&#xff08;注意&…

抠图软件哪个好用?什么软件可以抠图换背景?

抠图软件哪个好用&#xff1f;在图片处理中&#xff0c;抠图换背景是一项常见的操作。很多新手可能会对此感到困惑&#xff0c;不知道应该使用什么软件来进行抠图换景。实际上&#xff0c;现在市面上有很多图片处理软件都具备抠图换背景的功能&#xff0c;每款软件都有其优缺点…

LVS负载均衡群集部署 DR模式

目录 DR模式直接路由 LVS-DR工作原理 LVS-DR 数据包流向分析 DR 模式的特点 DR模式 LVS负载均衡群集部署 DR模式直接路由 Direct Routing&#xff0c;简称DR模式&#xff0c;采用半开放式的网络结构&#xff0c;与TUN模式的结构类似&#xff0c;但各节点并不是分散在各地…