一雨田的专栏

伟人将复杂的事情变简单,小人将简单的事情变复杂

用户操作
[即时聊天] [发私信] [加为好友]
一雨田ID:dylgsy
91678次访问,排名1090,好友2人,关注者13人。
一雨田
dylgsy的文章
原创 41 篇
翻译 1 篇
转载 6 篇
评论 292 篇
最近评论
heray818:我的邮箱是:heray818@126.com
heray818:你好 能否也传我一份 谢谢了啊
救援隊募集:アダルトエロ不倫
モテ度審査員:童貞セフレナンパ
temp:很好
文章分类
收藏
    相册
    好友Blog
    圈内朋友
    sankt的专栏
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 代替 if-else,switch-case 的几种方法收藏

    新一篇: [转][荐]小菜编程成长记系列 | 旧一篇: 设计模式系列代码下载--VC++可编译工程

    if-else,switch-case 是判断逻辑的语句,只要我们需要分支,就可能要用到这种语句,在 C 的编程风格中,更是动则需要这种判断语句,问题是这种判断语句如果多了,就会毁坏代码的可读性和维护性,增加了代码的“臭味”。那现在的面向对象编程时代,我们是否有些方法来代替呢?嗯,是有的,C++语言提供的多态、模版等特性就非常适合于编写代替 if-else、switch-case 的代码。

    我们举一个简单的例子来说明。一个事件的检查函数 CheckEvent(int nEvent)  判断事件的到来,并执行相应的操作。如果使用 if-else 或 switch-case 的话,代码如下:

    // 使用IF-ELSE的函数
    void CheckEvent(int nEvt)
    {
     if(nEvt == 1)
      cout << "1" << endl;
     if(nEvt == 2)
      cout << "2" << endl;
    }

    //  调用代码如下
    void main()
    {
     int nEvent = 1;
     CheckEvent(nEvent);
     int nEvent = 2;
    CheckEvent(nEvent);
    }

    下面我们用多态来代替之:

    // 第一种代替IF-ELSE的方法
    class CEvent
    {
    public:
     virtual void Show() = 0;
    };

    class CEvent1: public CEvent
    {
    public:
     virtual void Show()
     {
      cout << "1" << endl;
     }
    };

    class CEvent2 : public CEvent
    {
    public:
     virtual void Show()
     {
      cout << "2" << endl;
     }
    };

    void CheckEventNoIfElse(CEvent *pEvt)
    {
     pEvt->Show();
    }

    //  调用代码如下
    void main()
    {
     // 第一种 多态技术
     CEvent1 evt1;
     CEvent2 evt2;
     CheckEventNoIfElse(&evt1);
     CheckEventNoIfElse(&evt2);
    }

    看到多态的用途了吧,在 CheckEvent 中不用再出现判断代码了。

    多态属于一种动态的方法,我们也可以使用模版技术(一种属于静态的方法):

    // 第二种代替IF-ELSE的方法
    template<class T>
    void CheckEventTemplate(T *evt)
    {
     evt->Show();
    }

    // 调用代码如下
    void main()
    {
     // 第二种 模版技术
     CEvent1 evt1;
     CEvent2 evt2;
     CheckEventTemplate(&evt1);
     CheckEventTemplate(&evt2);
    }

    另外,我们也可以使用一些设计模式来代替 if-else switch-case 这种判断选择的代码,例如 state模式,就是代替switch-case 的一种很好的方法,《敏捷》里也有提到,可参考之。也可参考本人的《设计模式简单代码之State模式》。实际 State 模式也就是使用了C++中委托和多态的技术。

    好了,上面说了一些方法,希望能对你们有用,另外可能总结得不完全,希望知道其他方式的朋友不吝赐教。谢谢!

    发表于 @ 2006年10月18日 15:39:00|评论(loading...)|编辑

    新一篇: [转][荐]小菜编程成长记系列 | 旧一篇: 设计模式系列代码下载--VC++可编译工程

    评论

    #YLYC 发表于2006-10-19 08:13:00  IP: 210.149.56.*
    如题
    #突击召唤师 发表于2006-10-19 08:58:00  IP: 170.252.155.*
    想法不错,可惜例子差劲的离谱,前言不搭后语的。
    #ft... 发表于2006-10-19 12:48:00  IP: 207.46.89.*
    很明显你没有写过有什么程序……用多态和 template 代替分支语句完全就是驴唇不对马嘴
    #一雨田 发表于2006-10-19 10:54:00  IP: 211.156.179.*
    前言不搭后语的??

    哈哈,举这个例子只是为了简单说明,再说,举些复杂的例子也没什么意思,难读难懂。倒不如用一个简单的例子把意图说明白好。我认为是这样的。:)

    而且,使用面向对象的方法代替 IF-ELSE 和 SWITCH-CASE 也不一定会让代码简化阿。多态和模版不是仙丹,只是在某些情况下会对代码质量有一定的帮助。所以是否要用和在哪里用就见人见智咯。
    #cg 发表于2006-10-19 12:32:00  IP: 219.134.64.*
    傻得离谱,没见过如此SB
    #deerchao 发表于2006-10-19 12:35:00  IP: 125.33.174.*
    例子实在是太差了.
    #faint 发表于2006-10-19 13:30:00  IP: 130.214.25.*
    这样的垃圾文章也能上首页,混稿费吧?
    #一雨田 发表于2006-10-19 14:21:00  IP: 211.156.179.*
    to ft...

    如果你没见过用多态和template来代替分支语句的话,我也不知道说什么了。。。。。。

    to 在这骂的人:
    恩,我是SB了,本来希望能抛砖引玉,能有一些感兴趣的人出来平心静气的讨论一些具体的技术,谁知道,却引来了一班人骂我SB。

    我不知道你们骂我是为了什么呢?我这篇文章上了首页,不爽?这个技术你们没兴趣,或者根本对你们没任何帮助?还是骂了我能让你心情舒畅继而容光焕发导致工作效率疯狂提升?

    1、我只是用心去写文章,至于上不上首页没多想了,而且也没稿费的。什么骗稿费。。。
    2、这个技术如果你们没兴趣,大可不看,免得浪费诸位的时间。
    3、如果对你们没帮助,也可以不看,或者能不吝指点一下小弟,哪里需要改进,哪里不好。而不是一味狂骂,这样我肯定非常佩服你!

    看了一些牛人的BLOG,例如孟岩,王咏刚等,我的感觉就是无论怎么样,都会有些人在骂,为什么不能平心静气讨论些东西呢?非要骂人才能显得你的技术水平高吗?才能抬高你自己吗?技术界不应该这样的,有长处的,如果能分享大家会很尊敬你,有短处的大家说出来,一起讨论,一起提高,没什么意见的大可以做个过客,一笑而过。而不是左一声垃圾,右一声SB。这样做除了让人怀疑你的素质和破坏整个技术界的治学气氛之外,完全没半点帮助。

    衷心希望一些喜欢骂的人,能静下心来,大家一起进步。谢谢。

    另外,我承认我的这个例子是有点差劲了,对不起,因为我还有别的事情要做。要想一个好例子也是要花时间的。我以后会继续努力写好文章。谢谢。
    #cybercake 发表于2006-10-19 20:25:00  IP: 217.66.62.*
    条件语句什么的是最基本的语法元素,改头换面可以,但是其本质不会改变。区别只在于是谁写的而已。
    #cybercake 发表于2006-10-19 20:27:00  IP: 217.66.62.*
    更正一下,应该说是控制元素:P
    #yzx110 发表于2006-10-19 09:37:00  IP: 61.49.126.*
    想法不错,可惜例子差劲的离谱,前言不搭后语的。
    哈哈,我也是这句话,
    看到这个例子,我是不会用多态代替if-else或者switch-case了
    #null 发表于2006-10-19 10:10:00  IP: 222.66.97.*
    傻得离谱
    #zousoft 发表于2006-10-20 02:27:00  IP: 89.245.113.*
    不错,我觉得这是用简单工厂模式代替传统if的例子。还有模板。楼主要是能更进一步讲出这样做对程序扩展和维护带来的好处就更好了。总的来说还是不错的。
    #tom 发表于2006-10-19 10:14:00  IP: 202.106.235.*
    State 模式
    #路人甲 发表于2006-10-20 04:48:00  IP: 59.32.128.*
    另外,我承认我的这个例子是有点差劲了,对不起,因为我还有别的事情要做。要想一个好例子也是要花时间的。我以后会继续努力写好文章。谢谢。
    ---------------------------
    既然忙,也别急着发文,例子不好,反而有反效果
    比如模版那个,看上去就觉得还不如if简洁
    例子要体现该想法的优势,而是符合想法

    对胡乱谩骂的人没想法
    #ss 发表于2006-10-20 09:18:00  IP: 61.185.221.*
    这个例子不好。

    nEvt 可以用一个变量保存不同状态。

    CEvent1 evt1;
    CEvent2 evt2;
    是两个不同类型的变量啊。

    你能不能写用一个变量就能取代if-else的?
    #kwbplcz 发表于2006-10-20 11:12:00  IP: 220.163.19.*
    而且,使用面向对象的方法代替 IF-ELSE 和 SWITCH-CASE 也不一定会让代码简化阿。多态和模版不是仙丹,只是在某些情况下会对代码质量有一定的帮助。所以是否要用和在哪里用就见人见智咯。
    --------------------------------------------------------
    面向对象的方法作用是用来代替if/else么,真正的多态的作用你理解么,是为了实现方便的扩展,当继承自父类的子类增加时,父类不需要知道也不需要修改,而if/else是在写程序时就要考虑到所有可能情况。怎么能拿来跟if/else比较,甚至说“代替if/else”也不一定会简化代码.
    #noname 发表于2006-10-20 11:31:00  IP: 219.142.186.*
    你的字体太小,没心思看下去
    #shi 发表于2006-10-21 03:01:00  IP: 125.96.8.*
    例子真TMD一坨屎,狗屁不通!
    #一男 发表于2006-10-21 19:11:00  IP: 60.3.161.*
    模拟 Smalltalk 的重复、选择:
    struct Integer{
    template<typename Fn>
    void times(Fn& fn){ for (i = n_; i != 0; --i) fn(); }
    int n_;
    Integer(int n):n_(n){}
    };
    struct DoSth {
    void operator()(){ do_something(); }
    };
    int main(){
    Integer n = 10;
    n.times(DoSth());
    return 0;
    }
    #Ricepig 发表于2006-10-22 23:16:00  IP: 221.216.175.*
    还可以用Hashtable替代结构简单内容庞大的switch
    #hyg2008 发表于2006-10-23 12:56:00  IP: 219.137.27.*
    没有意义!
    明明这么简单的东西,你非要把它搞得这么复杂。
    #bright 发表于2006-10-24 14:06:00  IP: 219.137.197.*
    老实说,我也觉得这个例子实在有点boring
    多态确实可以简化使用者,但是这不是多态的目的,dt的目的,简而言之,就是抽象
    #bright 发表于2006-10-24 14:09:00  IP: 219.137.197.*
    马的,难得有心情写几句评论,没想该s的csdn竟然保存出错,狂cao阿
    #summer7 发表于2006-10-24 21:59:00  IP: 219.242.112.*
    评论的似乎脑筋都死了一些,而且见闻不够广博。
    if else是面向过程的方法。
    楼主的是面向对象的方法。

    在一些经典的c++书籍中提到过这个例子。
    #bright 发表于2006-10-27 18:08:00  IP: 61.144.34.*
    summer7真是一个sb
    " if else是面向过程的方法".................
    真tm弱智,面向对象就不用if else了?!
    if else只是代码的流程控制用,与是否面向对象有个屁关系
    超sb!
    #bright 发表于2006-10-27 18:18:00  IP: 61.144.34.*
    马的,还是觉得不过瘾
    本来像summer7这种菜鸟兼sb不值一骂的,不过刚才撒了一泡尿,想想为了帮助summer7这种超级菜鸟的成长,还是要骂多几句,点拨点拨。
    summer7,首先,你要搞明白啥叫面向对象,为什么要使用所谓的面向对象的方法来进行分析。其次,不要全盘相信书上说的,要自己思考,要有自己的理解和见解,这样才能提高自己的水平。
    还有,最重要一点:你妈自己的面向对象根本没吃透,就上来这里扮专家对其他人指指点点,这是最不能容忍的。做人要谦虚,才能进步!切记切记!
    #bright 发表于2006-10-27 18:32:00  IP: 61.144.34.*
    再说了,if else或者switch有什么不好?作为程序员需要关注的不是这些无谓的东西,更应去关注比如当数据量为100w时,我的这个功能会出现哪些问题。作为架构师要关注的是我这个4g内存2颗cpu的sco 能否承受在每天上午10点接近3000用户的高峰访问期的压力等等。同志们呐,我们要多点考虑怎样才能提升系统层面和业务层面的水平,而不是争执与怎样写代码更好看;如果真的要纠缠细节,我提个问题,summer7看你懂不,c++里面的list有什么特性?set又是什么?
    #bright 发表于2006-10-27 18:37:00  IP: 61.144.34.*
    又说了,你丫真的有水平,写个编译器来看看呀!老哥我近来就在做这个事情(基于兴趣)。我正在做的是基于pl/0的扩充,就是增加一些feature ,比如数组,vector等。summer7你那么牛B,咱们比赛阿,谁能先把java的整个collection实现了谁就算赢。
    最后,你丫那么hi牛B,你能在2天内把一本900页的C++读完,并且理解80%么?!
    你丫就是一小毛孩,不骂不醒。
    你丫要是知错能改,并且在gz,我倒是可以考虑教你一些东西,包括做人和技术方面的。
    #bright 发表于2006-10-27 18:40:00  IP: 61.144.34.*
    最后总结,
    骂丫真累!
    要是我部门有这种货色,立马炒!
    #一雨田 发表于2006-10-29 21:40:00  IP: 219.135.213.*
    晕了,BRIGHT,有必要那么好火气吗?

    我说一句吧,SUMMER7说的没错,在使用面向对象的方法时是可以使用多态来代替if-else,switch-case这种语句,但也不是说完全不用 if-else switch-case 啊,你可以看看WINDOWS SDK的大的消息循环(if-else, switch-case),不是在MFC中已经使用多态来代替了吗?又在WTL中不是使用模板来取代了吗?

    我这文章的意思是,当我们在面临分支选择的时候,可以考虑面向对象的这个特性。能帮助我们简化代码,因为分支选择肯定是有的,在汇编中不也有cmp,jnz吗?只是看谁来做,多态是编译器帮我们做了。所以我们的代码就简化了,逻辑就清晰了。

    另外觉得这个题目没必要花太多精力去争论了,只是随手总结了一下。而且请各位以技术讨论为主,别说气话,偏题了。:)
    #剑心通明 发表于2006-11-27 19:16:00  IP: 58.63.194.*
    何必要攻击人呢?也没见到你这些骂人的高手为中国的软件做了什么贡献
    #在阳光下变态 发表于2006-11-30 13:48:00  IP: 59.42.128.*
    就是,那些骂人的高手也没有为中国的骂人事业做出什么贡献,你看人家韩寒,你说你们活着有啥意义咧??还不如去~~~~~~~
    #cao bright 发表于2006-12-02 02:36:00  IP: 218.19.166.*
    路过,看了不爽。唉,bright一看就知道是鸟人,不想多说。
    #passos 发表于2006-12-19 16:51:14  IP:
    谁是SB一看自知…… 例子已经可以很简单充分的说明问题了,看不懂的……自己撞墙去吧
    #kingofbirdzjy 发表于2007-04-23 10:53:05  IP: 222.70.109.*
    一切问题的根源在于自己!
    那些不能理解作者意图的人也应该从自己身上去找问题。
    #oyd 发表于2007-07-21 14:19:05  IP: 61.135.152.*
    我不骂人
    可是我想,作者既然都不能在短时间内找到一个好例子来说明其好处,又怎么去指望读者能好好领会呢
    就好象一个老师说了一种很好的解题思路,但是举的例子不好,于是他对学生说,原理就是这样,我没有时间想一个好例子,你们看不懂的自己去撞墙吧。
    #lxj0511 发表于2007-08-21 16:54:32  IP: 221.230.82.*
    代替IF ELSE 用条件运算符可以

    IF(num1 > num2)
    max = num1;
    ELSE
    max = num2;

    max = num1 > num2 ? num1 : num2
    #HYCOLDRAIN 发表于2008-05-04 10:55:46  IP: 218.88.99.*
    有些人水平的确很低啊。作者写的很清楚了,看不懂又要骂别人,不成熟的表现啊。一雨田我支持你,看过你的简单代码设计模式,省了我不少时间,希望你能写出更好的文章。
    #xiaoyvr 发表于2008-06-19 01:59:33  IP: 125.33.175.*
    随便讨论技术的帖子竟然被骂成这样……
    例子的确没有太大吸引力,但是学过设计模式的都知道这里面意义在哪儿吧?
    那些连C++都看不上的牛人们就忽略我说的话吧……

    提出点例子里的问题,既然Event对象都有了,用函数重载来代替if-else应该是最佳的选择,多态毕竟是需要花费运行时开销的。此外例子里模板的方法也没有说清楚。

    我觉得这个例子最重要的并不是说明如何代替if-else,而是如何把show代码封装到不同的对象中去实现,而对外提供统一的接口去访问。

    大量的switch-case语句的替代方式也不止state模式一种,state模式也并不总是最好的选择,MFC的消息机制就是用事件驱动表的方式实现的。

    另外引用以下Modern C++ Design的方法给大家开阔一下思路。

    这是原来的函数:
    // 使用IF-ELSE的函数
    void CheckEvent(int nEvt)
    {
    if(nEvt == 1)
    cout << "1" << endl;
    if(nEvt == 2)
    cout << "2" << endl;
    }

    改造为:

    // 增加辅助模板类(用于将int值转换为类型)
    template<int v>
    struct Int2Type
    {
    // 这个要不要无所谓
    static const int value = v;
    }

    // 利用包装好的类型,进行函数重载(由于不需要使用参数,所以忽略参数名)
    void CheckEvent(Int2Type<1>)
    {
    cout<<1<<endl;
    }
    void CheckEvent(Int2Type<2>)
    {
    cout<<2<<endl;
    }

    调用代码:
    void main()
    {
    CheckEvent( Int2Type<1>() );
    CheckEvent( Int2Type<2>() );
    }

    这样也达到了去除if-else的目的,并且完全没有运行时开销。
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 一雨田