C++ 函数映射使用讲解


想想我们在遇到多语句分支时是不是首先想到的是 switc case 和 if else if ...

这2种方式在编码方面确实简单少,但是当分支达到一定数量后,特别是分支内部有嵌套大段代码或者再嵌套分支,

代码会显得异常臃肿,十分难以维护,对于if else if 语句过多的分支带来过多的判定句,势必会影响效率。


3种替代方法简述:
1.使用map,需要构建树和节点,比数组的方式消耗更多的内存,查询时间复杂度为Log(N),但扩展起来方便。


2.使用数组,查询直接索引定位, 一般来讲我们是连续的初始化数组,也就意味索引(type_func)到函数的映射要连续,

所以使用数组索引在扩展上来讲:例如增删元素是稍微麻烦点的。


3.使用C++的特性---抽象继承来实现,本文只讲前2种的使用,这种方式以后再补充。



我比较喜欢用代码结合实际来讲解,下面我将以一段事例代码来讲解如何使用这几种映射:



 

// 动物会一些动作
enum	type_func
{type_begin = -1,type_eat,type_sleep,type_walk,type_run,type_smile,type_cry,type_jump,type_max_size,
};class	CAnimal
{
public:typedef	int	(CAnimal::*ptr_func)(bool);protected:static map<type_func,ptr_func>	s_map;					static ptr_func					s_array[type_max_size];			public:CAnimal(){memset(s_array,0,sizeof(s_array));Init();	}// 需要映射函数的返回值 和 参数必须 统一int		eat		(bool= true)		{	return printf("eatn")	,1;	}int		sleep	(bool= true)		{	return printf("sleepn"),1;	}int		walk	(bool= true)		{	return printf("walkn")	,1;	}int		run		(bool= true)		{	return printf("runn")	,1;	}int		smile	(bool= true)		{	return printf("smilen"),1;	}int		cry		(bool= true)		{	return printf("cryn")	,1;	}int		jump	(bool= true)		{	return printf("jumpn")	,1;	}// 初始化void	Init	(){s_map[type_eat]		= &CAnimal::eat;s_map[type_sleep]	= &CAnimal::sleep;s_map[type_walk]	= &CAnimal::walk;s_map[type_run]		= &CAnimal::run;s_map[type_smile]	= &CAnimal::smile;s_map[type_cry]		= &CAnimal::cry;s_map[type_jump]	= &CAnimal::jump;s_array[type_eat]	= &CAnimal::eat;s_array[type_sleep]	= &CAnimal::sleep;s_array[type_walk]	= &CAnimal::walk;s_array[type_run]	= &CAnimal::run;s_array[type_smile]	= &CAnimal::smile;s_array[type_cry]	= &CAnimal::cry;s_array[type_jump]	= &CAnimal::jump;}// 一般做法是switc case 或者 if else...  // 其实这里看起来还不算糟糕,一方面这里我把每个模块内容都封装到相应函数了// 分支内部才会看起来相对简洁,实际编码中可能就不是你现在所看到的方式。void	Process (type_func type){switch (type){case type_eat:		eat();		break;case type_sleep:	sleep();	break;case type_walk:		walk();		break;case type_run:		run();		break;case type_smile:	smile();	break;case type_cry:		cry();		break;case type_jump:		jump();		break;}}// 很熟悉的感觉吧! :)void	Process2(type_func type){if (type_eat == type){eat();}else if (type_sleep == type){sleep();}else if (type_walk == type){walk();}else if (type_run == type){run();}else if (type_smile == type){smile();}else if (type_cry == type){cry();}else if (type_jump == type){jump();}}// 使用map 映射void ProcessByUseMap(int key, bool val){map<type_func,ptr_func>::iterator it =  s_map.find((type_func)key);if (it != s_map.end()){ptr_func pFun = it->second;if (pFun)	(this->*pFun)(val);}}// 使用数组 映射void ProcessByUseArray(int key, bool val){// 数组if (type_begin < key && type_max_size > key){ptr_func pFun = s_array[key];if (pFun)	(this->*pFun)(val);}}// 使用map 映射int	operator[]	(int key){map<type_func,ptr_func>::iterator it =  s_map.find((type_func)key);if (it != s_map.end()){ptr_func pFun = it->second;if (pFun)		return (this->*pFun)(false);}return NULL;}// 使用数组 映射int operator()	(int key,bool val){if (type_begin < key && type_max_size > key){ptr_func pFun = s_array[key];if (pFun)		return (this->*pFun)(val);}return NULL;}};map<type_func, CAnimal::ptr_func>	CAnimal::s_map;					
CAnimal::ptr_func					CAnimal::s_array[type_max_size];//
// 非成员函数
void	func_eat(int = 0)	{	}
void	func_run(int = 0)	{	}
void	func_walk(int =0)	{	}
void	func_cry(int = 0)	{	}typedef void	(*ptrFun)(int);
map<type_func,ptrFun>	g_map;
ptrFun					g_array[type_max_size];int _tmain(int argc, _TCHAR* argv[])
{//// 为了便于说明,下面代码不做安全检查// 非成员函数映射2种用法// initg_map[type_eat] = func_eat;g_map[type_run] = func_run;g_map[type_walk] = func_walk;g_map[type_cry] = func_cry;g_array[type_eat] = func_eat;g_array[type_run] = func_run;g_array[type_walk] = func_walk;g_array[type_cry] = func_cry;// usingg_map[type_eat](1);g_map[type_run](2);g_map[type_walk](3);g_map[type_cry](4);g_array[type_eat](1);g_array[type_run](2);g_array[type_walk](3);g_array[type_cry](4);//// 成员函数映射使用CAnimal Dog;Dog.Process(type_eat);Dog.ProcessByUseMap(type_run,true);Dog.ProcessByUseArray(type_cry,false);Dog[type_walk];Dog(type_sleep,true);Dog(type_run,false);return 1;
}


 

 


 

 

 


 

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

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

相关文章

昨天订了一台FSC Lifebook S6220

准备出差用 转载于:https://www.cnblogs.com/rexhost/archive/2005/03/24/124683.html

如何绕过 TPM 2.0 安装 Windows 11 操作系统?

方法一&#xff1a;删除 appraiserres.dll 文件1.下载 Windows 11 原版系统 ISO 镜像文件并解压到单独文件夹。&#xff08;一条不成熟的建议&#xff1a;现在请直接拔掉网线或关闭 WiFi&#xff09;2.打开已解压的文件&#xff0c;点击【source】文件夹。3.选择【appraiserres…

《悦趣式连锁反应》玩转STEM教育!529块积木元件,N+1款炫酷模型

▲数据汪特别推荐点击上图进入玩酷屋之前推荐的“小小机械师”成了孩子最受欢迎的玩具&#xff0c;玩了的孩子几乎没有不喜欢的。还有家长买多套送给朋友的孩子作为生日礼物。有家长来问&#xff0c;还有没有这种类型的新产品。和厂家咨询后&#xff0c;小木找到了一款“小小机…

域名的MX设置及校验方法

国内私募机构九鼎控股打造APP&#xff0c;来就送 20元现金领取地址&#xff1a;http://jdb.jiudingcapital.com/phone.html内部邀请码&#xff1a;C8E245J &#xff08;不写邀请码&#xff0c;没有现金送&#xff09;国内私募机构九鼎控股打造&#xff0c;九鼎投资是在全国股份…

昨天去驾校桩考

我通过了&#xff0c;当然。 封闭的电子考场&#xff0c;在场外待考的人们不惜屈尊偷看场内的“考题”&#xff0c;不过想来也没有什么看的&#xff0c;不还是平常一样的正反手进出库和移库嘛。 8:30正式开考之前&#xff0c;可以买票&#xffe5;10练习一次&#xff0c;有一位…

NET问答: JS 中有 LINQ SelectMany 方法的等价实现吗?

咨询区 toddmo&#xff1a;很遗憾&#xff0c;我在 Underscore 和 Jquery 中都没有找到对等实现&#xff0c;我的要求很简单&#xff0c;只要能做到 IE9 兼容即可。我的 SelectMany 实现如下&#xff1a;// SelectMany flattens it to just a list of phone numbers. IEnumerab…

java前补零工具类_java生成编码工具类,不足补0

~~~~~ 小小工具类&#xff01;你值得拥有简单粗暴&#xff0c;直接上代码import java.text.NumberFormat;/*** author: Abner* description: 编码工具类* date: Created on 2018/5/24*/public class SnUtils {/*** 生成 0000000000001 格式* param value 传入的数值* param min…

掌握神经网络,入门深度学习

从无人驾驶汽车到AlphaGo战胜人类&#xff0c;机器学习成为了当下最热门的技术。而机器学习中一种重要的方法就是深度学习。人工智能、机器学习与深度学习的关系深度学习的动机在于建立、模拟人脑进行分析学习的神经网络&#xff0c;整个过程就是使用多个处理层对数据进行高层抽…

麦克学摇滚(引用)

这支伟大的乐队开始于1987&#xff0c;在丹麦Arhus的一所中学&#xff0c;出现了一支业余性的乐队&#xff1b;Jascha Richter---一为对词曲创作极有天分&#xff0c;并且歌喉绝美的小伙子&#xff0c;与他的两位好友 —— Kare Wanscher (鼓手) 、Mikkel Lentz (吉它手)&#…

[旧博客]Python 第一次

决定学习Python&#xff0c;发现其需要安装的东西很小&#xff0c;只需要在官方网站下载和15MB左右的安装包&#xff0c;Python for windows。安装完毕就双击IDE快捷方式就打开IDE了。 你很发现IDE好像很面熟&#xff0c;对啊&#xff0c;Python原生的IDE就和一个windows笔记本…

罗马数字转换成数字java_C趣味编程百例(31)将阿拉伯数字转换为罗马数字

95.将阿拉伯数字转换为罗马数字将大于0小于1000的阿拉伯数字转换为罗马数字。阿拉伯数字与罗马数字的对应关系如下&#xff1a;*问题分析与算法设计题目中给出了阿拉伯数字与罗马数字的对应关系&#xff0c;题中的数字转换实际上就是查表翻译。即将整数的百、十、个位依次从整数…

NET问答: using 和 await using 有什么不同?

咨询区 Justin Lessard&#xff1a;我注意到在某些情况下&#xff0c;visual studio 经常推荐我这么做。await using var disposable new Disposable(); // Do something来替代下面的这种写法using var disposable new Disposable(); // Do something请问 using 和 await usi…

人造流星这种生日礼物,你有过吗?现在国外有了

全世界只有3.14 % 的人关注了数据与算法之美数据汪列举了不同“级别”的富豪是如何庆生的&#xff0c;大家看看自己处于什么水平。三流土豪的孩子过生日&#xff0c;看的是蜡烛...二流土豪的孩子过生日&#xff0c;看的是烟花...那么一流土豪的孩子看的又是什么呢&#xff1f;现…

Concurrent connection limit

这几天在做IIS 6上Web Service (WSE 2.0)的性能测试。在这个过程中陆续发现和解决了一些问题。 其中有一个问题比较有意思。我和项目组的同事发现&#xff0c;不论我们用C#写的模拟客户端用多少并发量来连接Web Service&#xff0c;服务器端监测到的并发连接数&#xff08;性能…

Material Master

02-03 03&#xff1a; 物料主的定义&#xff1a;相同的物料应该是同一个物料号。 在PP放面我们主要关心的是工厂 。 定义公司后在公司下面在定义工厂。 spro配置的时候我们可以在、后勤、物料管理、物料、创建&#xff1b; 后勤、生产、物料、创建 两种方式都可以进入物料创建…

java密码学原型算法_java密码学原型算法实现——双线性对.pdf

java密码学原型算法实现——双线性对Java 密码学原型算法实现——双线性对1、背景介绍如何使用jPBC 库进行双线性群初始化&#xff0c;包括&#xff1a;(1)质数阶双线性群(Prime-Order Bilinear Groups)&#xff1b;(2)合数阶双线性群(Composite-Order Bilinear Groups)&#x…

用啥Selenium?! .NET程序员就用自家的Playwright for .NET

提到用于Web应用程序自动化测试的工具&#xff0c;大家肯定第一个想到的就是Selenium。可以说&#xff0c;Selenium已经成为以编程方式自动化浏览器的事实标准。但是&#xff0c;Selenium作为老牌工具&#xff0c;也存在一些缺点&#xff0c;比如不支持Shadow DOM &#xff0c;…

每日一笑 | 一些关于集合的知识

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图源网络&#xff0c;侵权删&#xff09;

Digest

一场倾盆大雨。站立着面对这场大雨吧&#xff01;让它的钢铁般的光芒刺穿你。你在那想把你冲走的雨水中飘浮&#xff0c;但你还是要坚持&#xff0c;昂首屹立&#xff0c;等待那即将来临的无穷无尽的阳光的照耀。 转载于:https://www.cnblogs.com/bcpl/archive/2005/05/18/1578…

iOS之NSString

做了不少时间的iOS开发了&#xff0c;现在在阅读官方文档&#xff0c;特意整理出来&#xff0c;没任何技术含量&#xff0c;纯粹是笔记形式&#xff0c;希望对自己对大家有些帮助。 首先&#xff0c;要理解NSString需要学习下字符编码&#xff08;ASCii&#xff0c;Unicode&…