code.club

 找回密碼
 立即註冊
搜索
查看: 9963|回復: 0
打印 上一主題 下一主題

為何需要列舉 enum?

[複製鏈接]
跳轉到指定樓層
樓主
發表於 2016-2-18 16:47:32 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
為什麼需要列舉類型
      編程語言中的所有特性都是為了滿足某種需求,達到某個目的還出現,列舉可以用來保存一組屬性的值.enum的全稱是enumeration意思是列舉,當用一個軟件時,有些頁面會有很多單選按鈕(radio button),這也特別適合用列舉來表示你舉了哪一個,光這樣說你可能還不能體現列舉的好處.如果沒列舉,表示一些組屬性的值你只能用一組數字,或者一組字符串.

     數字從字面上看不出任意意義,可讀性非常差,所以很少用.那就假如要你通過比較字符串來做很多種類判斷,比如if(HisTitle == "stadholder") else if(HistTile == "mayor") .如果讓你敲個幾十次你就知道是件多麻煩痛苦的事了,很多單詞如果敲錯一個意思就完全變了,這樣出現bug了也不容易找到.老是複製粘貼也較麻煩.所以字符串是編輯麻煩,容易出錯.如果要使用列舉就極大的方便我們敲代碼,集成開發工具中的智能感應會給你提示,敲個點號就帶出來了.而且列舉會做類型檢查,不會像字符串那樣只能靠你自己去對比.

列舉類型的內存分配問題
     上面我們講瞭如果沒有列舉,一般會想到用數字或字符串表示某個類別.這樣使用肯定不方便.也許你可能會想到用#define(巨集,宏定義)來表示.比如#define 市長"mayor" 或者#define 市長2這自然是一個方法,但一來嘛在C++中是不太推薦用#define(巨集,宏定義)的,盡量少用.因為C++是強類型的語言,希望通過類型檢查來降低程序中的很多錯誤,而#define(巨集,宏定義)只是在編譯期前做簡單替換,繞過了類型檢查,失去了強類型系統的優勢支撐. 二來嘛一組屬性值都是相關聯的信息,必須放到一起,放到一組.

關於常量的誤解
列舉類型成員是常量:這句話怎麼理解呢.也就是說enum MyEnum{ one = 1 , two , three} ;
與const int one = 1; const int two = 2; const int three = 3; 差不多是一樣的.
      說到常量其實有個非常誤導人的地方因為用#define(巨集,宏定義)#define可以定義的我們說是常量,這裡只涉及到簡單的替換自然不可能存在內存分配問題.但是用const定義的也叫常量,而const定義常量貌似跟定義一般的變量只多個const關鍵字.你可能會想當然認為常量都只是簡單替換,所以不存在內存分配.那按這個邏輯,豈不是const定義的常量,列舉類型都沒有內存分配?
實際上大部分時候確實是這樣的.但並非總是如此,有些情況會需要分配內存的.

1.不需要分配內存的情況
      如果定義常量const int one = 1;然後在其他地方只是把one作為右值賦值給其他變量那就不存在內存分配.但這裡的常量跟#define定義的常量不同,#define(巨集,宏定義)定義的常量是編譯前簡單替換掉,而不需要做類型檢查.而const定義的常量在編譯時會幫類型檢查,編譯完之後再做替換.所以編譯完之後就看不到const的信息了,轉換成對應的值.const定義的信息只是保存在符號表中.
      那同樣,如果只是enum MyEnum{ one = 1 , two , three} ;這樣定義一個列舉類型,然後也是簡單的作右值賦值給其他變量.比如int num = MyEnum:ne;那也只是保存信息在符號表中,編譯後被替換掉了.
      有人可能說如果用sizeof MyEnum測下會發現會是4(這是VS裡面,不同的編譯器可能不一樣)於是認為不管是列舉裡面有多少個元素內存分配都是4.實際上不是這意思,應該是定義一個MyEnum類型的列舉變量時會分配內存.這跟定義了一個類一樣,你用sizeof去測一個為也會看到大小,但我們知道只有當類實例化之後才實際分配內存的.

2.需要分配內存的情況
1.)const int one;是類的成員變量
2)的extern const int的1 = 123;   
3)const int的1 = 1; 為int * pConst =之一;

上面三種情況會需要分配內存.
而列舉類型,如果不是簡單的去給其他變量賦值,而是去定義一個列舉類型變量.
比如MyEnum grade = MyEnum:ne; //此時會分配4字節內存空間.(不過據說編譯器會做優化,如果列舉類型所有值用兩個字節表示就足夠了,那實際分配的會就只會是兩字節了.不一定就是默認的int類型的長度)

列舉類型具體用法
一般的用法是在全局域內定義一個列舉類型.比如
列舉MyEnum {一,二,三}
如果不顯式指定,就會把第一個值默認賦值為0,然後遞增1依次賦值.如果顯式指定了某個值,則它下一個是它加1.
所以上面的例子中默認one = 0; two = 1; three= 2;
如果顯式指定enum MyEnum { one, two = 3, three }
則1 = 0; 2 = 3; 3 = 4;
定義一個列舉類型就是MyEnum grade = MyEnum:ne;
類中使用列舉這是不太常用的用法.

在類中聲明一個列舉後,定義列舉類型就可以省掉那個域作用前綴.比如MyEnum my = one; 在相同的作用域內也不能出現某個變量的名字和列舉中的元素名字相同,也就是不能出現其他變量名字是on,two, three
另外列舉還有一種少見的用法是
enum { one ,two ,three}; 就是不指定一個名字,這樣我們自然也沒法去定義一些列舉類型了.此時就相當於const int one = 0;這樣定義三個常量一樣.
然後用的話就是int no = one;

回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

小黑屋|手機版|Archiver|code.club  

GMT+8, 2024-12-4 02:01 , Processed in 0.066429 second(s), 18 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表