enum
enum (enumerator,列舉),有關於列舉的意思,簡單的描述就是將自己定義的參考值或名稱,集合在一起
而這個集合在一起的型態,稱為列舉。舉幾個常見的列舉使用方式:
1. enum Day{ SUM , MON , TUE , WED , THU , FRI , SAT };
2. enum Suit{ club , diamond , heart , spade } ;
3. enum Status{ CONTINUE , WON , LOST };
4. enum Month{ JAN=1 , FEB , MAR , APR , MAY , JUN , JUL , AUG , SEP , OCT , NOV , DEC };
5. enum Sex{ F , M };
6. enum Boolean { FALSE , TRUE } ;
我想還有很多常見的enum被使用著,會在學習的路上看得更多的。那enum到底是蝦米東東呢?
先來說enum內部的符號(標準名稱為enumerator,列舉元)到底有什麼意思,舉上列1.來說
若第一個名稱沒有初始值時
第一個名稱SUM的值就是0,下一個就加1,以此類推,也就是

SUM = 0 , MON = 1 , TUE = 2 , WED = 3 , THU = 4 , FRI = 5 , SAT = 6
沒有看到程式好像說服不了人 ,來看個簡單的"C語言"例子:
	#include <stdio.h>

	int main()
	{
		enum Day{ SUM , MON , TUE , WED , THU , FRI , SAT } six;

		for(six = SUM ; six <=SAT ; ++six)
		{
			printf("%d\n",six);
		}

		return 0;
	}

自己開起編譯器來試試吧!
那能不能一個一個設定呢?當然可以,像這樣:
enum Day{ SUM=6 , MON=12 , TUE=0 , WED=7 , THU=-1 , FRI=4 , SAT=9 };
那再執行下面的程式:
	#include <stdio.h>

	int main()
	{
		enum Day{ SUM=6 , MON=12 , TUE=0 , WED=7 , THU=-1 , FRI=-1 , SAT=9 } six;

		for(six = SUM ; six <=SAT ; ++six)
		{
			printf("%d\n",six);
		}

		return 0;
	}
輸出是6 7 8 9 而不是 6 12 0 7 -1 -1 9six++;的動作並不是往下一個列舉元,而是在現在的列舉元所表示的值加上1,這一點要注意!
有沒有注意到列舉元的值可正、可負、可為零、可重覆
但正數的範圍到那裡呢?負載的範圍到那裡呢?
根據ISO/IEC 14882:1998(E)7.2 Enumeration declarations提到
列舉元的值可以是另一個列舉元或整數值(signed int)
signed int中的int型態,應該要依據編譯器而定,作者判斷是如此
在VCint指的是long int
所以列舉元值的範圍就-2147483648~2147483647
如果超過這個值的話,就產生溢位(Overflow)!
所以現在知道要如何定義一個列舉了嗎?在複習一下:
一個列舉(enumeration)的定義,其中需要列舉元(enumerator)並且給予一個常數(constant value)常數表達式(constant expression);若沒有給予常數值(constant value)或常數表達式(constant expression)
時,第一個列舉元(enumerator)會被設定為0,下一個列舉元就是目前這個列舉元加1
列舉中的列舉元被視為常數(constant),在編譯期間(compile-time)時,列舉元的值會被決定了,執行下列程式
看看會有什麼狀況:

	#include <stdio.h>

	int main()
	{
		enum Day{ SUM , MON , TUE , WED , THU , FRI , SAT } ;

		SUM = 10;
	
		return 0;
	}
應該會出現這樣的錯誤訊息:'=' : left operand must be l-value
由於編譯結束後,列舉元已被視為常數,所以它並不是一個l-value,簡單來說常數是一個數值,並沒有實際的位扯
另外在C語言中列舉型態運算過程中,會被轉換成整數來運算。
基本上enum的特性大致介紹完畢,若不完整的地方建議參考書籍,但重點應該都有提到了。那程式的應用方面
,可能作者無法做介紹,請見諒。但並沒有結束,介紹幾個問題或應用
(1)enumCC++有什麼不同呢?
	#include <stdio.h>

	int main()
	{
		enum Day{ SUM , MON , TUE , WED , THU , FRI , SAT } six;

		for(six = SUM ; six <=SAT ; ++six)
		{
			printf("%d\n",six);
		}

		return 0;
	}
你分別在CC++中測試,也就是就以上的程式儲存附檔名為.C.CPP分別測試看看有什麼狀況
在C語言中,測試應該是沒有問題的,而在C++中會出現狀況:

 binary '++' : 'enum main::Day' does not define this operator or a conversion to a type acceptable 
                   to the predefined operator
錯誤顯示:在main中型態enum Day並沒有定義++這個運算子(operator)或轉換

註:作者是使用VC6.0,而有一位網友Jerry使用BCB5.5測試並不會有以上的錯誤
          Jerry認為VC6.0C++列舉型別的++運算子檢查比BCB5.5來的嚴謹。
          作者認為Jerry的判斷的確是有道理的,所以附加說明。

仔細回去翻閱C++的書籍,看列舉的說明是什麼。
在C語言中,列舉型別的運算過程中,會被轉換成整數運算,所以運算的動作(++--...)在編譯器已定義好了。
在C++中,列舉型別是使用者自訂型態(user-defined type),因為是自訂型態,所以運算的動作使用
者必須自己建立起,並沒有內建(built-in)於編譯器中。 
因為上面的程式並沒有定義列舉型態++的動作,所以編譯器無法判辨出++的動作是什麼。
若要能夠動作的話,就需要使用到C++的運算子多載(Operator overloading)或代替的方式
(a)運算子多載(enum放到main外面,運算子多載上面)#include <stdio.h>

	enum Day{ SUM , MON , TUE , WED , THU , FRI , SAT };

	Day& operator++(Day& current)
	{
		return current = ( SAT == current ) ? SUM : Day(current+1) ;
	}

	int main()
	{
		Day six;
		for(six = SUM ; six<=SAT ; ++six)		
		{
			printf("%d\n",six);
		}
		return 0;
	}

結果會無限迴圈哦!應該知道為什麼吧!

(b)利用整數變數(這個方法並沒有利用到enum型態的變數,所以這個應該不算是解決的方式囉!)
	#include <stdio.h>

	enum Day{ SUM , MON , TUE , WED , THU , FRI , SAT };

	int main()
	{
		int Day_value;

		for(Day_value = SUM ; Day_value <=SAT ; ++Day_value)
		{
			printf("%d\n",Day_value);
		}
		return 0;
	}
continue...

參考文章:
(1)Template Metaprograms
(2)A gentle introduction to Template Metaprogramming with C++
(3)Intelligent 'enum's in C++ Applications 
(4)C Enumeration Declarations
(5)C++ Enumeration Declarations
(6)Enumeration Constants vs. Constant Objects

回目錄
Written By James On 2004/02/08 

Hosted by www.Geocities.ws

1