跳轉到內容

C++ 程式設計

來自華夏公益教科書,開放的書籍,為開放的世界

enum 關鍵字用於建立一個名為 name 的列舉型別,該型別包含 name-list 中的元素。var-list 引數是可選的,可用於在宣告時建立該型別的例項。

語法
    enum name {name-list} var-list;

例如,以下程式碼建立了所需的資料型別

enum card_suit {Clubs,Diamonds,Hearts,Spades};
card_suit first_cards_suit=Diamonds;
card_suit second_cards_suit=Hearts;
card_suit third_cards_suit=0; //Would cause an error, 0 is an "integer" not a "card_suit" 
card_suit forth_cards_suit=first_cards_suit; //OK, they both have the same type.

這行程式碼建立了一個新的資料型別 "card_suit",它只能取四個可能的值之一:"Clubs"、"Diamonds"、"Hearts" 和 "Spades"。一般來說,enum 命令採用以下形式

enum new_type_name { possible_value_1,
                     possible_value_1,
                     /* ..., */
                     possible_value_n
} Optional_Variable_With_This_Type;

而第二行程式碼建立了一個具有此資料型別的新變數,並將其初始化為 Diamonds 的值。其他行建立了此新型別的其他變數,並展示了一些可能的(和不可能的)初始化。

在內部,列舉型別儲存為整數,從 0 開始,每增加一個新的可能資料型別值就增加 1。

enum apples { Fuji, Macintosh, GrannySmith };
enum oranges { Blood, Navel, Persian };
apples pie_filling = Navel; //error can't make an apple pie with oranges.
apples my_fav_apple = Macintosh;
oranges my_fav_orange = Navel; //This has the same internal integer value as my_favorite_apple

//Many compilers will produce an error or warning letting you know your comparing two different quantities.
if(my_fav_apple == my_fav_orange) 
  std::cout << "You shouldn't compare apples and oranges" << std::endl;

雖然列舉型別不是整數,但在某些情況下會轉換為整數。例如,當我們嘗試將列舉型別傳送到標準輸出時。

例如

enum color {Red, Green, Blue};
color hair=Red;
color eyes=Blue;
color skin=Green;
std::cout << "My hair color is " << hair << std::endl;
std::cout << "My eye color is " << eyes << std::endl;
std::cout << "My skin color is " << skin << std::endl;
if (skin==Green)
  std::cout << "I am seasick!" << std::endl;

將產生以下輸出

My hair color is 0
My eye color is 2
My skin color is 1
I am seasick!

我們可以透過引入一個包含我們列舉型別名稱的陣列來改進此示例,例如

std::string color_names[3]={"Red", "Green", "Blue"};
enum color {Red, Green, Blue};
color hair=Red;
color eyes=Blue;
color skin=Green;
std::cout << "My hair color is " << color_names[hair] << std::endl;
std::cout << "My eye color is " << color_names[eyes] << std::endl;
std::cout << "My skin color is " << color_names[skin] << std::endl;

在這種情況下,hair 在作為索引陣列時會自動轉換為整數。此技術與顏色 Red 在內部儲存為 "0",Green 在內部儲存為 "1",而 Blue 在內部儲存為 "2" 的事實密切相關。小心! 可以覆蓋這些預設的列舉型別內部值的選項。

這可以透過在 enum 中簡單地設定值來完成,例如

enum color {Red=2, Green=4, Blue=6};

事實上,沒有必要為列舉型別的每個值設定整數。在這種情況下,編譯器將簡單地將前一個可能值的數值增加 1。

考慮以下示例

enum colour {Red=2, Green, Blue=6, Orange};

這裡,"Red" 的內部值為 2,"Green" 的內部值為 3,"Blue" 的內部值為 6,"Orange" 的內部值為 7。在使用此功能時要小心,因為內部值不需要是唯一的。

在算術表示式中,列舉型別也會自動轉換為整數。這使得能夠為列舉型別的內部表示選擇特定的整數變得很有用。

可以為標準計算機螢幕的寬度和高度列舉。這可以使程式執行有意義的計算,同時仍然保持列舉型別的優點。

enum screen_width {SMALL=800, MEDIUM=1280};
enum screen_height {SMALL=600, MEDIUM=768};
screen_width MyScreenW=SMALL;
screen_height MyScreenH=SMALL;
std::cout << "The number of pixels on my screen is " << MyScreenW*MyScreenH << std::endl;

需要注意的是,列舉型別中使用的內部值是常量,在程式執行過程中無法更改。

也許值得注意的是,雖然列舉型別可以轉換為整數以便進行算術運算,但它們無法進行迭代。

例如

enum month { JANUARY=1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER};

for( month cur_month = JANUARY; cur_month <= DECEMBER; cur_month=cur_month+1)
{
  std::cout << cur_month << std::endl;
}

這將無法編譯。問題在於 for 迴圈。迴圈中的前兩個語句沒有問題。我們可以建立一個新的 month 變數並對其進行初始化。我們還可以比較兩個月,在這種情況下,它們將作為整數進行比較。我們不能遞增 cur_month 變數。"cur_month+1" 的計算結果為整數,該整數可能無法儲存到 "month" 資料型別中。

在上面的程式碼中,我們可以嘗試透過替換 for 迴圈來修復這個問題

for( int monthcount = JANUARY; monthcount <= DECEMBER; monthcount++)
{
  std::cout << monthcount  << std::endl;
}

這將有效,因為我們可以遞增整數 "monthcount"。

華夏公益教科書