枚舉類型在編譯器處理之後
⑴ C++中的枚舉類型怎麼使用
C++中的枚舉類型使用:
1、枚舉enum的用途
寫程序時,我們常常需要為某個對象關聯一組可選alternative屬性.例如,學生的成績分A,B,C,D等,天氣分sunny, cloudy, rainy等等。
更常見的,打開一個文件可能有三種狀態:input, output和append. 典型做法是,對應定義3個常數,即:
const int input = 1;
const int output = 2;
const int append = 3;
然後,調用以下函數:
bool open_file(string file_name, int open_mode);
比如,
open_file("Phenix_and_the_Crane", append);
這種做法比較簡單,但存在許多缺點,主要的一點就是無法限制傳遞給open_file函數的第2個參數的取值范圍,只要傳遞int類型的值都是合法的。(當然,這樣的情況下的應對措施就是在open_file函數內部判斷第二個參數的取值,只有在1,2,3范圍內才處理。) 使用枚舉能在一定程度上減輕這種尷尬(注1),它不但能實現類似於之前定義三個常量的功能,還能夠將這三個值組合起來成為獨一無二的組。例如:
enum open_modes {input = 1, output, append};
以上定義了open_modes為枚舉類型enumeration type。每一個命名了的枚舉都是唯一的類型,是一個類型標示器type specifier。例如,我們可以重新寫一個open_file函數: bool open_file(string file_name, open_modes om);
在open_modes枚舉中,input, output, append稱為枚舉子enumerator, 它們限定了open_modes定義的對象的取值范圍。這個時候,調用open_file函數和之前的方法還是一模一樣:
open_file("Phenix_and_the_Crane", append);
但是,如果傳遞給open_file的第二個參數不是open_modes枚舉類型值的話(注1),那麼編譯器就會識別出錯誤;就算該參數取值等價於input, output, append中的某個, 也一樣會出錯哦!例如:
open_file("Phenix_and_the_Crane", 1);
2、枚舉的定義
一個枚舉是一個類型,可以保存一組由用戶刻畫的值。定義之類,枚舉的使用很像一個整數類型。
枚舉的定義具有以下形式,即以關鍵詞enum開頭,接著一個可選的枚舉名,下來是由大括弧{}包含著一個由逗號分隔的枚舉子列表enumerators list:
enum [enumeration name] {enumerator1[=value1], enumerator2[=value2], ...};
3、枚舉子的類型和取值
枚舉子的類型就是它所在的那個枚舉,例如前面說到的open_modes枚舉中,input,output和append等枚舉子的類型都是open_modes。這種做法,其實是為了賦予用戶和編譯器一些有關該變數擬議中的用途的提示。
默認下,第一個枚舉子被賦值0,接下來的枚舉子取值是前面一個枚舉子的取值+1,例如:
enum weather {sunny, cloudy, rainy, windy};
其中
sunny == 0,
cloudy == 1,
rainy == 2,
windy == 3;
以上是默認情況,有時候我們希望顯式地指定某個枚舉子的值,那麼會出現什麼情況呢?看看:
enum some_fruit {apple = 3, orange, banana = 4, bear};
好了,apple == 3, banana == 4; 那麼orange和bear呢?記得前面說過一句,默認下」接下來的枚舉子取值是前面一個枚舉子的取值+1「。既然這兩個枚舉子沒有顯式賦值,那麼就按照默認規則辦事,所以 orange == 4, bear == 5.
從這個例子也可以看出,同一枚舉中枚舉子的取值不需要唯一。這樣有什麼用處呢?下面是個簡單的例子:
enum some_big_cities {
Guangzhou = 4,
Shenzhen = 4,
Hongkong = 4,
Shanghai = 2,
Beijing = 3,
Chongqi = 3
};
以上簡單地按區域,將五個城市按照華南(4),華東(2), 華北(3)的幾個城市分類了。
4、枚舉變數的定義、初始化和賦值
既然每個枚舉都是一個類型,那麼由這個類型自然可以聲明變數,例如,由前面定義的some_big_cities:
some_big_cities where_I_am;
需要注意的是,在聲明where_I_am時沒有初始化,如果這時列印where_I_am的值: enum some_big_cities {
Guangzhou = 4,
Shenzhen = 4,
Hongkong = 4,
Shanghai = 2,
Beijing = 3,
Chongqi = 5};
int main(void)
{
some_big_cities wh;
cout<<"the value is: "<<wh<<endl;
return 0;
}
輸出將是the value is: 1. 然而,如果聲明wh為全局變數,則另一種情況:
enum some_big_cities {Guangzhou = 1 Shenzhen = 1, Hongkong = 1,
Shanghai = 2, Beijing = 3, Chongqi = 5};
some_big_cities wh;
int main(void)
{
cout<<"the value is: "<<wh<<endl;
return 0;
}
輸出將是the value is: 0;
以上結果是在Visual C++ 2005 Express中得到,不知道其它編譯器情況如何,也不知為什麼得到這樣的結果。下來再找找資料。
定義一個枚舉變數時,可以給它初始化,例如:
some_big_cities wh = Guangzhou;
注意等號右邊只能取枚舉子中的某一個;特別地,以Guangzhou為例,雖然Guangzhou==4, 但以下初始化是出錯的:
some_big_cities wh = 4;
Visual C++ 2005編譯器提示:
error C2440: 'initializing' : cannot convert from 'int' to 'some_big_cities'
可見,不能直接地把一個整型賦值給一個枚舉變數,因為枚舉和整型是不同類型的,除非顯式轉換。關於枚舉與整型的關系,後面再講。
除了初始化,枚舉變數也有賦值運算:
some_big_cities wh;
wh = Guangzhou;
wh = Shanghai;
或者
some_big_cities wh1 = Guangzhou;
some_big_cities wh2 = Shanghai;
wh2 = wh1;
5、枚舉的取值范圍
如果某個枚舉中所有枚舉子的值均非負,該枚舉的表示範圍就是[0:2^k-1],其中2^k是能使所有枚舉子都位於此范圍內的最小的2的冪;如果存在負的枚舉值,該枚舉的取值范圍就是[-2^k,2^k-1].例如:
enum e1 {dark, light}; //范圍0:1
enum e3 {min = -10, max = 1000}; //范圍-1024:1023
6、枚舉與整型的關系
整型值只能顯式地轉換成一個枚舉值,但是,如果轉換的結果位於該枚舉取值范圍之外,則結果是無定義的。
enum e1 {dark = 1, light = 10};
e1 VAR1 = e1(50); //無定義
e1 VAR2 = e1(3); //編譯通過
在這里也說明了不允許隱式地從整型轉換到枚舉的原因,因為大部分整型值在特定的枚舉里沒有對應的表示。
至於枚舉可以當作特定的整型數來用的例子,從open_modes可以體會。
7、自定義運算符
枚舉是用戶自定義類型,所以在用戶可以為它定義自身的操作,例如++或者<<等。但是,在沒有定義之前,不能因為枚舉像整型就可以默認使用,例如:
enum SomeCities
{
zhanjiang,
Maoming,
Yangjiang,
Jiangmen,
Zhongshan
};
SomeCities oneCity;
for (oneCity = zhanjiang; oneCity != Zhongshan; ++oneCity)
{
cout<<oneCity<<endl;
}
以上的++OneCity是沒有定義的,在Visual C++ 6 編譯下得到如下錯誤:
error C2675: unary '++' : 'enum main::SomeCities' does not define this operator or a conversion to a type acceptable to the predefined operator
8、Sizeof
一個枚舉類型的sizeof就是某個能夠容納其范圍的整型的sizeof, 而且不會大於sizeof(int), 除非某個枚舉子的值不能用int或者unsigned int來表示。
在32位機器中,sizeof(int)一般等於4。前面介紹的所有枚舉,例如,
enum SomeCities
{
zhanjiang,
Maoming,
Yangjiang,
Jiangmen,
Zhongshan
};
計算其sizeof, 可能是1,也可能是是4。在我的intel E2160雙核、32位機器中,得到4。 -----------------------------------------------------------------------------------
[注1, Begin]
由於通過將整型數顯式轉換就可能得到對應枚舉類型的值,所以聲明一個枚舉來達到限制傳遞給函數的參數取值范圍還是力不從心的,以下是一個例子:
enum SomeCities
{
zhanjiang=1, //1
Maoming, //2
Yangjiang, //3
Jiangmen, //4
Zhongshan = 1000 //1000
};
void printEnum(SomeCities sc)
{
cout<<sc<<endl;
}
int main(void)
{
SomeCities oneCity = SomeCities(50); //將50通過顯式轉換,為oneCity賦值 printEnum(oneCity); //在VC++ 6 編譯器下得到50輸出
return 0;
}
以上例子說明,雖然SomeCities的定義里沒有賦值為50的枚舉值,但是,由於50在該枚舉的取值范圍內,所以通過顯式聲明得到一個有定義的枚舉值,從而成功傳遞給printEnum函數。
⑵ java枚舉類型
java 枚舉類型enum 的使用
最近跟同事討論問題的時候,突然同事提到我們為什麼java 中定義的常量值不採用enmu 枚舉類型,而採用public final static 類型來定義呢?以前我們都是採用這種方式定義的,很少採用enum 定義,所以也都沒有注意過,面對突入起來的問題,還真有點不太清楚為什麼有這樣的定義。既然不明白就抽時間研究下吧。
Java 中的枚舉類型採用關鍵字enum 來定義,從jdk1.5才有的新類型,所有的枚舉類型都是繼承自Enum 類型。要了解枚舉類型,建議大家先打開jdk 中的Enum類簡單讀一下,這個類裡面定義了很多protected 方法,比如構造函數,如果要使用這些方法我們可以把枚舉類型定義到當前類中。每個枚舉類型,都有自己的名字和順序,當我們輸出一個枚舉類型的時候,會輸入枚舉類型的name ,具體可以參考下面的例子。
一、 通常定義常量方法
我們通常利用public final static 方法定義的代碼如下,分別用1 表示紅燈,3 表示綠燈,2 表示黃燈。
package com.csdn.myEnum;
public class Light {
/* 紅燈 */
public final static int RED =1;
/* 綠燈 */
public final static int GREEN =3;
/* 黃燈 */
public final static int YELLOW =2;
}
二、 枚舉類型定義常量方法
枚舉類型的簡單定義方法如下,我們似乎沒辦法定義每個枚舉類型的值。比如我們定義紅燈、綠燈和黃燈的代碼可能如下:
public enum Light {
RED , GREEN , YELLOW ;
}
我們只能夠表示出紅燈、綠燈和黃燈,但是具體的值我們沒辦法表示出來。別急,既然枚舉類型提供了構造函數,我們可以通過構造函數和覆寫toString方法來實現。首先給Light 枚舉類型增加構造方法,然後每個枚舉類型的值通過構造函數傳入對應的參數,同時覆寫toString 方法,在該方法中返回從構造函數中傳入的參數,改造後的代碼如下:
public enum Light {
// 利用構造函數傳參
RED (1), GREEN (3), YELLOW (2);
// 定義私有變數
private int nCode ;
// 構造函數,枚舉類型只能為私有
private Light( int _nCode) {
this . nCode = _nCode;
}
@Override
public String toString() {
return String.valueOf ( this . nCode );
}
}
三、 完整示例代碼
枚舉類型的完整演示代碼如下:
package com.csdn.myEnum;
import java.util.EnumMap;
import java.util.EnumSet;
public class LightTest {
// 1. 定義枚舉類型
public enum Light {
// 利用構造函數傳參
RED (1), GREEN (3), YELLOW (2);
// 定義私有變數
private int nCode ;
// 構造函數,枚舉類型只能為私有
private Light( int _nCode) {
this . nCode = _nCode;
}
@Override
public String toString() {
return String.valueOf ( this . nCode );
}
}
/**
* @param args
*/
public static void main(String[] args ) {
// 1. 遍歷枚舉類型
System. out .println( " 演示枚舉類型的遍歷 ......" );
testTraversalEnum ();
// 2. 演示 EnumMap 對象的使用
System. out .println( " 演示 EnmuMap 對象的使用和遍歷 ....." );
testEnumMap ();
// 3. 演示 EnmuSet 的使用
System. out .println( " 演示 EnmuSet 對象的使用和遍歷 ....." );
testEnumSet ();
}
/**
* 演示枚舉類型的遍歷
*/
private static void testTraversalEnum() {
Light[] allLight = Light.values ();
for (Light aLight : allLight) {
System. out .println( " 當前燈 name : " + aLight.name());
System. out .println( " 當前燈 ordinal : " + aLight.ordinal());
System. out .println( " 當前燈: " + aLight);
}
}
/**
* 演示 EnumMap 的使用, EnumMap 跟 HashMap 的使用差不多,只不過 key 要是枚舉類型
*/
private static void testEnumMap() {
// 1. 演示定義 EnumMap 對象, EnumMap 對象的構造函數需要參數傳入 , 默認是key 的類的類型
EnumMap<Light, String> currEnumMap = new EnumMap<Light, String>(
Light. class );
currEnumMap.put(Light. RED , " 紅燈 " );
currEnumMap.put(Light. GREEN , " 綠燈 " );
currEnumMap.put(Light. YELLOW , " 黃燈 " );
// 2. 遍歷對象
for (Light aLight : Light.values ()) {
System. out .println( "[key=" + aLight.name() + ",value="
+ currEnumMap.get(aLight) + "]" );
}
}
/**
* 演示 EnumSet 如何使用, EnumSet 是一個抽象類,獲取一個類型的枚舉類型內容<BR/>
* 可以使用 allOf 方法
*/
private static void testEnumSet() {
EnumSet<Light> currEnumSet = EnumSet.allOf (Light. class );
for (Light aLightSetElement : currEnumSet) {
System. out .println( " 當前 EnumSet 中數據為: " + aLightSetElement);
}
}
}
執行結果如下:
演示枚舉類型的遍歷 ......
當前燈 name : RED
當前燈 ordinal : 0
當前燈: 1
當前燈 name : GREEN
當前燈 ordinal : 1
當前燈: 3
當前燈 name : YELLOW
當前燈 ordinal : 2
當前燈: 2
演示 EnmuMap 對象的使用和遍歷 .....
[key=RED,value= 紅燈 ]
[key=GREEN,value= 綠燈 ]
[key=YELLOW,value= 黃燈 ]
演示 EnmuSet 對象的使用和遍歷 .....
當前 EnumSet 中數據為: 1
當前 EnumSet 中數據為: 3
當前 EnumSet 中數據為: 2
四、 通常定義常量方法和枚舉定義常量方法區別
以下內容可能有些無聊,但絕對值得一窺
1. 代碼:
public class State {
public static final int ON = 1;
public static final Int OFF= 0;
}
有什麼不好了,大家都這樣用了很長時間了,沒什麼問題啊。
首先,它不是類型安全的。你必須確保是int
其次,你還要確保它的范圍是0 和1
最後,很多時候你列印出來的時候,你只看到 1 和0 ,
但其沒有看到代碼的人並不知道你的企圖,拋棄你所有舊的public static final 常量
2. 可以創建一個enum 類,把它看做一個普通的類。除了它不能繼承其他類了。(java 是單繼承,它已經繼承了Enum),
可以添加其他方法,覆蓋它本身的方法
3. switch() 參數可以使用enum 了
4. values() 方法是編譯器插入到enum 定義中的static 方法,所以,當你將enum 實例向上轉型為父類Enum 是,values() 就不可訪問了。解決辦法:在Class中有一個getEnumConstants() 方法,所以即便Enum 介面中沒有values() 方法,我們仍然可以通過Class 對象取得所有的enum 實例
5. 無法從enum 繼承子類,如果需要擴展enum 中的元素,在一個介面的內部,創建實現該介面的枚舉,以此將元素進行分組。達到將枚舉元素進行分組。
6. 使用EnumSet 代替標志。enum 要求其成員都是唯一的,但是enum 中不能刪除添加元素。
7. EnumMap 的key 是enum ,value 是任何其他Object 對象。
8. enum 允許程序員為eunm 實例編寫方法。所以可以為每個enum 實例賦予各自不同的行為。
9. 使用enum 的職責鏈(Chain of Responsibility) . 這個關繫到設計模式的職責鏈模式。以多種不同的方法來解決一個問題。然後將他們鏈接在一起。當一個請求到來時,遍歷這個鏈,直到鏈中的某個解決方案能夠處理該請求。
10. 使用enum 的狀態機
11. 使用enum 多路分發
⑶ C語言問題,關於枚舉類型的
與編譯器的行為有關,枚舉實際上也是一個整形。
但在c/c++強類型的前提下,這是不行的。如果允許,那麼你的編譯器不夠嚴謹或設置問題。
就拿你的例子說,枚舉里只有4個值,但你給賦值超過4,這就是錯的。
⑷ C語言enum類型的問題
這個本來就沒有錯啊!
枚舉類型是派生自System.Enum的一種獨特的值類型,用於聲明一組命名的常數。每種枚舉類型均有一種基礎類型,此基礎類型可以使除char類型以外的任何整型。
枚舉元素的默認基礎類型為int 默認情況下,第一個枚舉元素的值為0,後面每個枚舉元素的值依次遞增1 。如
emum weekday{sun,mon,tue,wed,thu,fri,sat},在此枚舉中,sun的值為0 ,mon為1 以此類推。也可emum weekday{sun=1,mon,tue,wed=sun,thu,fri,sat},強制第一個枚舉元素sun的值為1,mon為2,tue為3,而wed又強制為1,依次類推。
⑸ C++枚舉類型
函數本身是要求返回枚舉類型的,怎麼能返回string呢?這一般會報錯的,也許某些編譯器不會,但至於返回什麼,就看那個不報錯的編譯器怎麼處理了。如果是返回枚舉類型,那他不是返回一個完整的字元串,而只是返回你定義的枚舉類型中那個字元串的值。
⑹ 枚舉類型
對於C#中的枚舉類型不僅可以提高程序的可讀性,而且可以減少因底層值發生改變而導致的程序改動。另外一個好處是枚舉類型是強類型,以enum類型作為參數傳遞時,接受方法必須有一個相同的匹配參數;否則編譯器將會報錯。
枚舉可用在數據的表示,如性別:男,女,和結果的表示,如一個方法的幾種可能的返回值.
如何用好枚舉? 要徹底,枚舉就是枚舉,不要認為它是數字或字元串,雖然它們之間可以轉換.
枚舉如何與其它類型轉換?
enum Country
{
中國=1,
美國=2,
}
1.enum 變 string
Country c = Country.中國;
string sc = c.ToString();
Debug.Assert(sc == "中國");
2.enum 變 int
int ic = (int)c;
Debug.Assert(ic == 1);
3.int 變 enum
int ic = 1;
Country c = (Country)i;
Debug.Assert(c == Country.中國);
4.string 變 enum
Country c = (Country)Enum.Parse(typeof(Country), "中國");
Debug.Assert(c == Country.中國);
大概是這樣,許多公司使用枚舉不多,但枚舉在我們公司得到廣泛的應用.枚舉的好處是易寫(寫的時候清楚知道應該使用哪個值,而不是去想這里該返回1還是2)易處理(處理的時候對應每個枚舉值都清楚知道它的含義,而不是想1代表什麼)易讀(讀的時候含義很直接明了),關於枚舉的詳細歡迎加QQ群:7229630來討論.
⑺ 枚舉類型的使用
具體的枚舉類型的使用可以去msdn去看,從你的錯誤提示看,都是提示類型不匹配的問題。
enum BAND CurrentBand =Band_MW;
enum BAND band;
band=CurrentBand+1;
以上語法是不對的,因為雖然Band_MW有個數字的序號,但是整形和枚舉類型還是不同的,需要進行牽制類型轉換。針對這個我寫了個小程序。
#include<stdio.h>
enum BAND {Band_LW,Band_MW,Band_FM,Band_SW,Band_OIRT};
void setFrequency (enum BAND band){
printf("%d\n",band);
}
void main(){
enum BAND CurrentBand =Band_MW;
enum BAND band;
band=(BAND)((int)CurrentBand+1);//這里一定要轉換。
setFrequency(band);
}
這樣是可以的。我還要說一下,我是用的是VS2008,對不同的編譯器可能會不同,希望有幫助。