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的三种方法的更多相关文章

  1. php生成随机数的三种方法

    php生成随机数的三种方法 如何用php生成1-10之间的不重复随机数? 例1,使用shuffle函数生成随机数. <?php$arr=range(1,10);shuffle($arr);for ...

  2. Linux启动新进程的三种方法

    程序中,我们有时需要启动一个新的进程,来完成其他的工作.下面介绍了三种实现方法,以及这三种方法之间的区别. 1.system函数-调用shell进程,开启新进程system函数,是通过启动shell进 ...

  3. Eclipse插件安装的三种方法

    转自:http://www.blogjava.net/tangzurui/archive/2008/06/30/211669.html  整理了一下格式. (前两种安装方式以多国语言包的安装为例) 1 ...

  4. 三种方法实现PCA算法(Python)

    主成分分析,即Principal Component Analysis(PCA),是多元统计中的重要内容,也广泛应用于机器学习和其它领域.它的主要作用是对高维数据进行降维.PCA把原先的n个特征用数目 ...

  5. 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 ...

  6. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

  7. C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?

    C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...

  8. python 多线程编程之threading模块(Thread类)创建线程的三种方法

    摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...

  9. 【转】三种方法让你在I2C通信中同时和多个从机通信

    ref:http://tieba.baidu.com/p/3769008030 对于不同地址的模块就不用多说了,直接分别对其地址进行通信即可.那么若拿到相同地址的模块,或者直接是相同的多个模块怎么办呢 ...

随机推荐

  1. Linux下更改正确国内时间

    Linux使用小Tips 整理些Linux些常遇到的问题. Linux下设置时间 提供两种最根本有效的方式,就是更改时区.这里以更改为国内上海时间例子,其他地方时区同理. 方法一 备份文件 mv /e ...

  2. 初识Linq to Entity

    技术介绍: LINQ(Language Integrated Query,语言集成查询)是一组用于C#和VB.NET语言的扩展,它允许编写C#或者VB.net代码,以与查询数据库相同的方式操作内存数据 ...

  3. POJ 2155 Matrix (矩形)

    date:公元2017年7月19日适逢周三: location:清北集训 杭州 point:二维树状数组/二维差分 Matrix Time Limit: 3000MS   Memory Limit:  ...

  4. 【codeforces 765F】 Souvenirs

    http://codeforces.com/problemset/problem/765/F (题目链接) 题意 给出$n$个数的序列,$m$次询问,每次查询区间$[l,r]$之间相差最小的两个数的差 ...

  5. 如何修改Windows程序的权限?

    修改程序的权限需要用到3个函数: 1. 获取进程的令牌句柄: OpenProcessToken 2. 查找特权类型的ID: LookupPrivilegeValue 3. 修改进程的特权:Adjust ...

  6. ES6学习(一)搭建环境

    作为一名后端小开发,业务工作需要将后台系统重构一番,许多同事都已经使用前后分离搭建项目,为了不拖后腿自己在家摸索ES6的新特性,真心不知道什么ES3,ES5,一上来就开始搞ES6,在此留下学习笔记,方 ...

  7. linux中awk工具的使用

    awk是一个非常好用的数据处理工具.相较于sed常常一整行处理,awk则比较倾向于一行当中分成数个“字段”处理,awk处理方式如下: $ awk '条件类型1{动作1} 条件类型2{动作2} ...' ...

  8. 栈(C语言实现)

    栈是一种线性数据结构,顺序可能是 LIFO(后进先出)或 FILO(先进先出). 堆栈主要有三个基本操作: 1.push,把元素压入栈 2.pop,从栈中弹出元素(同时从栈中移除),最后加入的第一个被 ...

  9. SSH项目整合

    其实框架的整合无非就是jar包和配置文件: struts2.spring.Hibernate这三个框架,分清楚什么作用就好配置了. jar包我们就不说了,这里看下配置文件吧: struts.xml: ...

  10. Chapter10(泛型算法)--C++Prime笔记

    关键:算法通过在迭代器上进行操作来实现类型无关.算法不改变所操作序列的大小. 1.算法大多都定义在algorithm头文件中,标准库还在头文件numeric中定义了一组数值泛型算法. 2.泛型算法永远 ...