1.常规switch

  1. enum EnumType
  2. {
  3. enumOne,
  4. enumTwo,
  5. enumThree
  6. };
  7.  
  8. void showMessage(int type)
  9. {
  10. switch(type)
  11. {
  12. case enumOne:
  13. printf("This is message one\n");
  14. break;
  15. case enumTwo:
  16. printf("This is message two\n");
  17. break;
  18. case enumThree:
  19. printf("This is message three\n");
  20. break;
  21. default:
  22. printf("This is wrong message\n");
  23. break;
  24. }
  25. }
  26.  
  27. int main()
  28. {
  29. //常规switch
  30. showMessage(enumOne);
  31. showMessage(enumTwo);
  32. showMessage(enumThree);
  33.  
  34. return 0;
  35. }

2.多态+std::map取代switch

  1. #include <map>
  2.  
  3. enum EnumType
  4. {
  5. enumOne,
  6. enumTwo,
  7. enumThree
  8. };
  9.  
  10. class Base
  11. {
  12. public:
  13. Base(){}
  14. virtual ~Base(){}
  15. virtual void showMessage(){}
  16. };
  17.  
  18. class MessageOne:public Base
  19. {
  20. public:
  21. MessageOne(){}
  22. ~MessageOne(){}
  23. void showMessage()
  24. {
  25. printf("This is message one\n");
  26. }
  27. };
  28.  
  29. class MessageTwo:public Base
  30. {
  31. public:
  32. MessageTwo(){}
  33. ~MessageTwo(){}
  34. void showMessage()
  35. {
  36. printf("This is message two\n");
  37. }
  38. };
  39.  
  40. class MessageThree:public Base
  41. {
  42. public:
  43. MessageThree(){}
  44. ~MessageThree(){}
  45. void showMessage()
  46. {
  47. printf("This is message three\n");
  48. }
  49. };
  50.  
  51. int main()
  52. {
  53. //多态+std::map取代switch
  54. std::map<int,Base*> baseMap;
  55. baseMap.insert(std::make_pair(enumOne,new MessageOne));
  56. baseMap.insert(std::make_pair(enumTwo,new MessageTwo));
  57. baseMap.insert(std::make_pair(enumThree,new MessageThree));
  58. baseMap[enumOne]->showMessage();
  59. baseMap[enumTwo]->showMessage();
  60. baseMap[enumThree]->showMessage();
  61.  
  62. return 0;
  63. }

  上述完全是一个面向过程到面向对象的转变:将每个case分支都作为一个子对象,然后用C++语言的多态性去动态绑定。这样做确实是带来了性能上的损失,但是在当今的CPU计算能力而言,这是可以忽略的,而它带来的好处却很有用:
(1)分支的增减只要继续派生即可;
(2)子类代表了一个case,比必须用type去硬编码的case语句更加具有可读性;
(3)代码的可读性增强,使得分支的维护性增加;
(4)面向对象的思想更加符合人看世界的方式;

(5)避免了漏写break语句造成的隐蔽错误。

3.函数指针+std::map取代switch

  1. #include <map>
  2.  
  3. enum EnumType
  4. {
  5. enumOne,
  6. enumTwo,
  7. enumThree
  8. };
  9.  
  10. void showMessageOne()
  11. {
  12. printf("This is message one\n");
  13. }
  14.  
  15. void showMessageTwo()
  16. {
  17. printf("This is message two\n");
  18. }
  19.  
  20. void showMessageThree()
  21. {
  22. printf("This is message three\n");
  23. }
  24.  
  25. int main()
  26. {
  27. //函数指针+std::map取代switch
  28. typedef void (*func)();
  29.  
  30. std::map<int,func> funcMap;
  31. funcMap.insert(std::make_pair(enumOne,showMessageOne));
  32. funcMap.insert(std::make_pair(enumTwo,showMessageTwo));
  33. funcMap.insert(std::make_pair(enumThree,showMessageThree));
  34. funcMap[enumOne]();
  35. funcMap[enumTwo]();
  36. funcMap[enumThree]();
  37.  
  38. return 0;
  39. }

  

值得注意的是函数指针要用typedef定义,否则报错。

4.状态模式取代switch

关于设计模式中的状态模式可参考:C++设计模式——状态模式

直接上代码。

  1. #include <stdio.h>
  2. class Context;
  3. class State
  4. {
  5. public:
  6. State(){}
  7. virtual ~State (){}
  8. virtual void showMessage(Context *pContext)=0;
  9. };
  10.  
  11. class MessageOne:public State
  12. {
  13. public:
  14. MessageOne(){}
  15. ~MessageOne(){}
  16. void showMessage(Context *pContext)
  17. {
  18. printf("This is message one\n");
  19. }
  20. };
  21.  
  22. class MessageTwo:public State
  23. {
  24. public:
  25. MessageTwo(){}
  26. ~MessageTwo(){}
  27. void showMessage(Context *pContext)
  28. {
  29. printf("This is message two\n");
  30. }
  31. };
  32.  
  33. class MessageThree:public State
  34. {
  35. public:
  36. MessageThree(){}
  37. ~MessageThree(){}
  38. void showMessage(Context *pContext)
  39. {
  40. printf("This is message three\n");
  41. }
  42. };
  43.  
  44. class Context
  45. {
  46. public:
  47. Context(State *pState) : m_pState(pState){}
  48.  
  49. void Request()
  50. {
  51. if (m_pState)
  52. {
  53. m_pState->showMessage(this);
  54. }
  55. }
  56.  
  57. void ChangeState(State *pState)
  58. {
  59. m_pState = pState;
  60. }
  61.  
  62. private:
  63. State *m_pState;
  64. };
  65.  
  66. int main()
  67. {
  68. State *pStateA = new MessageOne();
  69. State *pStateB = new MessageTwo();
  70. State *pStateC = new MessageThree();
  71. Context *pContext = new Context(pStateA);
  72. pContext->Request();
  73.  
  74. pContext->ChangeState(pStateB);
  75. pContext->Request();
  76.  
  77. pContext->ChangeState(pStateC);
  78. pContext->Request();
  79.  
  80. delete pContext;
  81. delete pStateC;
  82. delete pStateB;
  83. delete pStateA;
  84.  
  85. return 0;
  86. }

  

三种方法的运行结果如下图所示:

[转]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. centos7防火墙操作

    启动: systemctl start firewalld 关闭: systemctl stop firewalld 查看状态: systemctl status firewalld 开机禁用 : s ...

  2. @Primary 注解引出的问题

    @Primary 注解 刚看到这个,还以为是持久层的注解呢,以为和@Id差不多,一查才知道,这两个风马牛不相及,反倒和@Qualifier以及@Resource有点像了,但是相比而言,后面两个更加的灵 ...

  3. 计算机网络【6】—— 从浏览器输入URL到显示页面发生了什么

    当在浏览器地址栏输入网址,如:www.baidu.com后浏览器是怎么把最终的页面呈现出来的呢?这个过程可以大致分为两个部分:网络通信和页面渲染. 一.网络通信 互联网内各网络设备间的通信都遵循TCP ...

  4. 图片上传预览,兼容IE

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. java 每一个对象都是根据hashCode区别的 每次返回不同的内存地址

    可以通过hashCode比较对象,hashCode如果重写的话 返回的内存地址是一样的 则不能创建对象

  6. 测试人员如何"提问"

    本文打算谈谈QA如何高质量的“提问”   写这些的初衷其实比较简单,作为一个测试老鸟,加入了一些很有质量的测试圈子,也在不同的公司带过不少新人,常常会碰到低效率的“提问”,主要表现如下:   1.问题 ...

  7. LDA-Latent Dirichlet Allocation 学习笔记

    以下内容主要基于<Latent Dirichlet Allocation>,JMLR-2003一文,另加入了一些自己的理解,刚开始了解,有不对的还请各位指正. LDA-Latent Dir ...

  8. FutureTask 源码解析

    FutureTask 源码解析 版权声明:本文为本作者原创文章,转载请注明出处.感谢 码梦为生| 刘锟洋 的投稿 站在使用者的角度,future是一个经常在多线程环境下使用的Runnable,使用它的 ...

  9. CSU1911 Card Game 【FWT】

    题目链接 CSU1911 题解 FWT模板题 #include<algorithm> #include<iostream> #include<cstdlib> #i ...

  10. 调用Android系统设置项

    Intent mIntent = new Intent(); ComponentName comp = new ComponentName("com.android.settings&quo ...