程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C/C++中一個簡單的enum手法(idiom)

C/C++中一個簡單的enum手法(idiom)

編輯:關於C++

今天寫程序的時候,又用到這個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. 下一頁:
Copyright © 程式師世界 All Rights Reserved