[转]C++ 取代switch的三种方法
1.常规switch
- enum EnumType
- {
- enumOne,
- enumTwo,
- enumThree
- };
- void showMessage(int type)
- {
- switch(type)
- {
- case enumOne:
- printf("This is message one\n");
- break;
- case enumTwo:
- printf("This is message two\n");
- break;
- case enumThree:
- printf("This is message three\n");
- break;
- default:
- printf("This is wrong message\n");
- break;
- }
- }
- int main()
- {
- //常规switch
- showMessage(enumOne);
- showMessage(enumTwo);
- showMessage(enumThree);
- return 0;
- }
2.多态+std::map取代switch
- #include <map>
- enum EnumType
- {
- enumOne,
- enumTwo,
- enumThree
- };
- class Base
- {
- public:
- Base(){}
- virtual ~Base(){}
- virtual void showMessage(){}
- };
- class MessageOne:public Base
- {
- public:
- MessageOne(){}
- ~MessageOne(){}
- void showMessage()
- {
- printf("This is message one\n");
- }
- };
- class MessageTwo:public Base
- {
- public:
- MessageTwo(){}
- ~MessageTwo(){}
- void showMessage()
- {
- printf("This is message two\n");
- }
- };
- class MessageThree:public Base
- {
- public:
- MessageThree(){}
- ~MessageThree(){}
- void showMessage()
- {
- printf("This is message three\n");
- }
- };
- int main()
- {
- //多态+std::map取代switch
- std::map<int,Base*> baseMap;
- baseMap.insert(std::make_pair(enumOne,new MessageOne));
- baseMap.insert(std::make_pair(enumTwo,new MessageTwo));
- baseMap.insert(std::make_pair(enumThree,new MessageThree));
- baseMap[enumOne]->showMessage();
- baseMap[enumTwo]->showMessage();
- baseMap[enumThree]->showMessage();
- return 0;
- }
上述完全是一个面向过程到面向对象的转变:将每个case分支都作为一个子对象,然后用C++语言的多态性去动态绑定。这样做确实是带来了性能上的损失,但是在当今的CPU计算能力而言,这是可以忽略的,而它带来的好处却很有用:
(1)分支的增减只要继续派生即可;
(2)子类代表了一个case,比必须用type去硬编码的case语句更加具有可读性;
(3)代码的可读性增强,使得分支的维护性增加;
(4)面向对象的思想更加符合人看世界的方式;
(5)避免了漏写break语句造成的隐蔽错误。
3.函数指针+std::map取代switch
- #include <map>
- enum EnumType
- {
- enumOne,
- enumTwo,
- enumThree
- };
- void showMessageOne()
- {
- printf("This is message one\n");
- }
- void showMessageTwo()
- {
- printf("This is message two\n");
- }
- void showMessageThree()
- {
- printf("This is message three\n");
- }
- int main()
- {
- //函数指针+std::map取代switch
- typedef void (*func)();
- std::map<int,func> funcMap;
- funcMap.insert(std::make_pair(enumOne,showMessageOne));
- funcMap.insert(std::make_pair(enumTwo,showMessageTwo));
- funcMap.insert(std::make_pair(enumThree,showMessageThree));
- funcMap[enumOne]();
- funcMap[enumTwo]();
- funcMap[enumThree]();
- return 0;
- }
值得注意的是函数指针要用typedef定义,否则报错。
4.状态模式取代switch
关于设计模式中的状态模式可参考:C++设计模式——状态模式
直接上代码。
- #include <stdio.h>
- class Context;
- class State
- {
- public:
- State(){}
- virtual ~State (){}
- virtual void showMessage(Context *pContext)=0;
- };
- class MessageOne:public State
- {
- public:
- MessageOne(){}
- ~MessageOne(){}
- void showMessage(Context *pContext)
- {
- printf("This is message one\n");
- }
- };
- class MessageTwo:public State
- {
- public:
- MessageTwo(){}
- ~MessageTwo(){}
- void showMessage(Context *pContext)
- {
- printf("This is message two\n");
- }
- };
- class MessageThree:public State
- {
- public:
- MessageThree(){}
- ~MessageThree(){}
- void showMessage(Context *pContext)
- {
- printf("This is message three\n");
- }
- };
- class Context
- {
- public:
- Context(State *pState) : m_pState(pState){}
- void Request()
- {
- if (m_pState)
- {
- m_pState->showMessage(this);
- }
- }
- void ChangeState(State *pState)
- {
- m_pState = pState;
- }
- private:
- State *m_pState;
- };
- int main()
- {
- State *pStateA = new MessageOne();
- State *pStateB = new MessageTwo();
- State *pStateC = new MessageThree();
- Context *pContext = new Context(pStateA);
- pContext->Request();
- pContext->ChangeState(pStateB);
- pContext->Request();
- pContext->ChangeState(pStateC);
- pContext->Request();
- delete pContext;
- delete pStateC;
- delete pStateB;
- delete pStateA;
- return 0;
- }
三种方法的运行结果如下图所示:
[转]C++ 取代switch的三种方法的更多相关文章
- php生成随机数的三种方法
php生成随机数的三种方法 如何用php生成1-10之间的不重复随机数? 例1,使用shuffle函数生成随机数. <?php$arr=range(1,10);shuffle($arr);for ...
- Linux启动新进程的三种方法
程序中,我们有时需要启动一个新的进程,来完成其他的工作.下面介绍了三种实现方法,以及这三种方法之间的区别. 1.system函数-调用shell进程,开启新进程system函数,是通过启动shell进 ...
- Eclipse插件安装的三种方法
转自:http://www.blogjava.net/tangzurui/archive/2008/06/30/211669.html 整理了一下格式. (前两种安装方式以多国语言包的安装为例) 1 ...
- 三种方法实现PCA算法(Python)
主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域.它的主要作用是对高维数据进行降维.PCA把原先的n个特征用数目 ...
- Viewing the interface of your Swift code,查看Swift代码的头文件的三种方法
Technical Q&A QA1914 Viewing the interface of your Swift code Q: How do I view the interface ...
- c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)
c#封装DBHelper类 public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...
- C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?
C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...
- python 多线程编程之threading模块(Thread类)创建线程的三种方法
摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...
- 【转】三种方法让你在I2C通信中同时和多个从机通信
ref:http://tieba.baidu.com/p/3769008030 对于不同地址的模块就不用多说了,直接分别对其地址进行通信即可.那么若拿到相同地址的模块,或者直接是相同的多个模块怎么办呢 ...
随机推荐
- centos7防火墙操作
启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status firewalld 开机禁用 : s ...
- @Primary 注解引出的问题
@Primary 注解 刚看到这个,还以为是持久层的注解呢,以为和@Id差不多,一查才知道,这两个风马牛不相及,反倒和@Qualifier以及@Resource有点像了,但是相比而言,后面两个更加的灵 ...
- 计算机网络【6】—— 从浏览器输入URL到显示页面发生了什么
当在浏览器地址栏输入网址,如:www.baidu.com后浏览器是怎么把最终的页面呈现出来的呢?这个过程可以大致分为两个部分:网络通信和页面渲染. 一.网络通信 互联网内各网络设备间的通信都遵循TCP ...
- 图片上传预览,兼容IE
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java 每一个对象都是根据hashCode区别的 每次返回不同的内存地址
可以通过hashCode比较对象,hashCode如果重写的话 返回的内存地址是一样的 则不能创建对象
- 测试人员如何"提问"
本文打算谈谈QA如何高质量的“提问” 写这些的初衷其实比较简单,作为一个测试老鸟,加入了一些很有质量的测试圈子,也在不同的公司带过不少新人,常常会碰到低效率的“提问”,主要表现如下: 1.问题 ...
- LDA-Latent Dirichlet Allocation 学习笔记
以下内容主要基于<Latent Dirichlet Allocation>,JMLR-2003一文,另加入了一些自己的理解,刚开始了解,有不对的还请各位指正. LDA-Latent Dir ...
- FutureTask 源码解析
FutureTask 源码解析 版权声明:本文为本作者原创文章,转载请注明出处.感谢 码梦为生| 刘锟洋 的投稿 站在使用者的角度,future是一个经常在多线程环境下使用的Runnable,使用它的 ...
- CSU1911 Card Game 【FWT】
题目链接 CSU1911 题解 FWT模板题 #include<algorithm> #include<iostream> #include<cstdlib> #i ...
- 调用Android系统设置项
Intent mIntent = new Intent(); ComponentName comp = new ComponentName("com.android.settings&quo ...