当前位置:主页   - 电脑 - 程序设计 - C/C++
C/C++中一个简单的enum手法(idiom)
来源:网络   作者:   更新时间:2012-02-08
收藏此页】    【字号    】    【打印】    【关闭

  今天写程序的时候,又用到这个idiom了,于是顺便贴出来。这个idiom蛮简单的,估计很多人都用过。今天主要是贴出来给新手参考(老手们就甭费时看此帖了)。

  为了说明这个手法具体该咋用,咱举一个简单的例子来说事儿。比方说要开发一个网络程序,其中需要统计各种网络协议的数据包数量。

  ★版本1

  假设一开始只需要处理HTTP和FTP两种协议。有些同学不假思索,立即会声明如下两个整数用于统计:

int nCntHttp = 0;
int nCntFtp = 0;

  猛一看,似乎没啥问题。但是,如果需求发生变更,又要增加两种协议:SMTP和SSH。然后,该同学会继续扩展上述代码,变为如下:

int nCntHttp = 0;
int nCntFtp = 0;
int nCntSmtp = 0;
int nCntSsh = 0;

  这时候,问题开始显露出来了。比方说要打印上述4统计值,就得写4个printf;再假如要用断言确保所有统计值大于零,也得写4个assert。这都是挺烦人的事儿。(当然啦,有些同学会把4个变量的打印写在一个printf中,但还是一样烦人)

  ★版本2

  这可咋办捏?某些同学就灵机一动,把上述代码修改为数组形式,上述的4个统计值依次放入数组中。具体如下:

  int nCntProto[4];

  /* 第0个是HTTP,第1个是FTP,第2个是SMTP,第4个是SSH */

  这样,无论是打印还是断言,都可以用for循环搞定,貌似挺方便的。但这么一来,引入了另一个问题。假设我在程序中要用到SMTP的统计数字,就得这么写代码:nCntProto[2]。这就造成了很不雅观的“Magic Number”!要知道,Magic Number可是代码的臭味之一啊(其弊端在“这里”曾经介绍过)。万一将来,数组中的存放顺序发生变化,那就完蛋了:好多用到Magic Number的代码都得跟着改。一旦漏改某处,引出Bug无数!

  ★版本3

  为了消除Magic Number,增加代码可读性和可维护性,有些同学开始打起enum的主意。在代码中增加了一组enum,具体如下:

enum PROTO
{
 PROTO_HTTP,
 PROTO_FTP,
 PROTO_SMTP,
 PROTO_SSH,
};

int nCntProto[4];

  这样,如果我需要用到SMTP的统计数字,我就不用写nCntProto[2],而是写nCntProto[PROTO_SMTP]。这样,可读性明显好多了。即使将来数组中的存放顺序发生变化,也没关系:只需稍微调整enum中常量的顺序即可,其它代码不用动。

  ★版本4

  但是,还是有一个不爽的地方。定义数组的语句用到了“4”这个Magic Number。万一将来需求继续变更,继续增加协议,那这个数字还得不断调整。不爽!

  这时候,终极版本隆重登场。请看如下代码:

enum PROTO
{
 PROTO_HTTP,
 PROTO_FTP,
 PROTO_SMTP,
 PROTO_SSH,

 PROTO_NUM /* 表示协议数量 */
};

int nCntProto[PROTO_NUM];

  这种写法的好处在于,没有任何一个Magic Number。不管是引用某个统计值还是循环遍历数组,都使用的是定义好的常量。

  当需求变更,需要增加新的协议,只要往enum中增加相应的enum常量即可(但要记得保证PROTO_NUM位于enum定义的末尾)。由于PROTO_NUM会自动跟着增长,所以其它的代码几乎不会受到影响。

  ★C++的补充说明

  上述代码同时适用于C和C++。不过,对于某些C++程序员,或许看不惯原始数组,觉得STL的容器类看起来比较顺眼。那也没啥大关系:只要把上述代码的数组声明修改为如下,其它的代码基本照旧。

std::vector<int> vctCntProto(PROTO_NUM);

  文章来源:

  http://program-think.blogspot.com/2009/04/c-cxx-enum-idiom.html

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明