有時候,你會想要定義一組相關的常數,例如,以一組常數來代表遊戲中動作:
#include <iostream>
using namespace std;
struct Action {
const static int STOP = 0;
const static int RIGHT = 1;
const static int LEFT = 2;
const static int UP = 3;
const static int DOWN = 4;
};
void play(int action) {
switch(action) {
case Action::STOP:
cout << "播放停止動畫" << endl;
break;
case Action::RIGHT:
cout << "播放向右動畫" << endl;
break;
case Action::LEFT:
cout << "播放向左動畫" << endl;
break;
case Action::UP:
cout << "播放向上動畫" << endl;
break;
case Action::DOWN:
cout << "播放向下動畫" << endl;
break;
default:
cout << "不支援此動作" << endl;
}
}
int main() {
play(Action::RIGHT);
play(Action::LEFT);
return 0;
}
這種方式雖然行得通,不過 play
接受的是 int
整數,這表示你可以傳入任何 int
整數,而不一定要是列舉的數值,雖然可以透過設計,令列舉的 static
成員為 Action
的實例,並令其成為單例(singleton)等,不過,C++ 本身就提供了 enum
來達到這類任務。例如:
#include <iostream>
using namespace std;
enum Action {
STOP, RIGHT, LEFT, UP, DOWN
};
void play(Action action) {
switch(action) {
case Action::STOP:
cout << "播放停止動畫" << endl;
break;
case Action::RIGHT:
cout << "播放向右動畫" << endl;
break;
case Action::LEFT:
cout << "播放向左動畫" << endl;
break;
case Action::UP:
cout << "播放向上動畫" << endl;
break;
case Action::DOWN:
cout << "播放向下動畫" << endl;
break;
default:
cout << "不支援此動作" << endl;
}
}
int main() {
play(Action::RIGHT);
play(LEFT);
play(1); // error: invalid conversion from 'int' to 'Action'
return 0;
}
enum
列舉的成員具有型態,以上例來說,STOP
等成員都是 Action
型態,因此 play
接受是 Action
的成員,就上例來說,Action
等成員,可見範圍會與使用 enum
處的範圍相同,因此上例可以直接使用 LEFT
而不一定使用 Action::
前置,然而,如果有其他 enum
列舉了同名的成員,省略 Action::
就會發生名稱衝突。
enum
列舉的成員,會有預設的對應整數,無範疇的列舉成員,在必須取得整數值的場合,會自動轉換為對應的整數,對應整數預設由 0 開始,也可以自行指定。例如:
enum Action {
STOP = 1, RIGHT, LEFT, UP, DOWN
};
就上例來說,Action::STOP
對應的整數為後續列舉成員沒有設定對應數值的話,會自動遞增 1,所以 Action::RIGHT
為 2、Action::LEFT
為 3,依此類推,然而列舉成員對應的常數值不需獨一無二,例如:
enum Action {
STOP = 1, RIGHT, LEFT = 1, UP, DOWN
};
對於無範疇的 enum
成員,C++ 標準只保證對應的整數型態,可以容納被指定的整數值,若無法容納則編譯錯誤,不過在 C++ 11 以後可以指定型態:
enum Action : int {
STOP, RIGHT, LEFT, UP, DOWN
};
C++ 11 以後也可以先宣告而不定義列舉成員:
enum Action : int;
C++ 11 可以定義有範疇的列舉成員,也就是可視範圍是在 enum
之內,使用時就必須加上型態前置:
#include <iostream>
using namespace std;
enum class Action {
STOP, RIGHT, LEFT, UP, DOWN
};
void play(Action action) {
switch(action) {
case Action::STOP:
cout << "播放停止動畫" << endl;
break;
case Action::RIGHT:
cout << "播放向右動畫" << endl;
break;
case Action::LEFT:
cout << "播放向左動畫" << endl;
break;
case Action::UP:
cout << "播放向上動畫" << endl;
break;
case Action::DOWN:
cout << "播放向下動畫" << endl;
break;
default:
cout << "不支援此動作" << endl;
}
}
int main() {
play(Action::RIGHT);
play(LEFT); // error: 'LEFT' was not declared in this scope
return 0;
}
定義有範疇的列舉時,可以使用 class
或 struct
,兩者等效,有範疇的列舉不會自動轉換為對應的整數值,必要時得明確指定轉型:
int action = static_cast<int>(Action::RIGHT);