枚舉類型可以將一組整型常量組織在一起;和類一樣,每個枚舉類型定義了一種新的類型;枚舉屬於字面常量類型。
C++包含兩種枚舉:限定作用域(C++11新標準引入)的和不限定作用域的:
定義限定作用域的枚舉類型的一般形式是:首先是關鍵字enum class(或者等價的使用struct),之後是枚舉類型名字以及用花括號括起來的以逗號分割開來的枚舉成員列表,最後是一個分號:
enum class open_modes{input,output,append};
定義不限定作用域的枚舉類型時省略關鍵字class(或struct),枚舉類型的名字是可選的:
enum color{red,yelow,blue};
enum {floatPrec = 6,doublePrec = 10,double_doublePrec = 10};
枚舉成員
在限定作用域的枚舉類型中,枚舉成員的名字遵循常規的作用域準則,並且在枚舉類型的作用域外是不可訪問的。與之相反,在不限定作用域的枚舉類型中,枚舉成員的作用域與枚舉類型本身的作用域相同:
//定義
enum color{red,yellow,green}; //不限定作用域的枚舉
enum stoplight{red,yellow,green}; //報錯:重複定義枚舉成員
enum class Peppers{red,yellow,green}; //正確,外面的被隱藏了
//使用
coler a = green; //正確
Peppers p = green; //報錯,這個green被認爲是color的
Peppers p2 = Peppers::red; //正確
默認情況下,枚舉成員的值是從0開始的,依次加1,不過是可以專門指定枚舉成員的值,並且枚舉成員的值也可以不唯一:
enum class intTypes{
charType = 8,shortType = 16,intType = 16,
longType = 32,long_longType = 64
};
枚舉成員是const的,因此在初始化枚舉成員時提供的枚舉值必須是常量表達式,即每個枚舉成員本身就是一條常量表達式,可以在任何需要常量表達式的地方使用枚舉成員。例如,定義枚舉類型的constexpr(有編譯器檢查變量是否是一個常量表達式)變量:
constexpr intTypes ch = intTypes::charType;
枚舉定義新的類型
和類一樣,枚舉也能定義新的類型,只要enum有名字,我們就能定義並初始化enum對象併爲該對象賦值,必須使用該類型的一個枚舉成員或該類型的另一個對象:
open_modes om = 2; //錯誤,2不是該枚舉的成員
om = open_modes::input; //正確
值得注意的是一個不限定作用域的枚舉類型的對象或是枚舉成員可以自動轉換成整型,可在需要的地方使用:
int i = color::red; //正確
int j = Peppers::red; //錯誤,限定作用域的枚舉類型不會進行隱式轉換。
指定enum大小
儘管每個enum都定義了唯一的類型,但實際上enum是由某種整數類型表示的。在C++11新標準中,可以在enum的名字後面加上冒號以及想在該enum中使用的類型:
enum intValues : unsigned long long {
charTyp = 255,shortTyp = 65535,intTyp = 65536,
longTyp = 4294967296UL,
long_longTyp = 18446744073709551615ULL
};
如果沒有指定類型,那麼限定作用域的枚舉的枚舉成員類型默認會是int,
對於不限定作用域的枚舉來說,不存在默認的類型,只知道成員的潛在類型足夠大,肯定能容納枚舉值。
枚舉類型的前置聲明
在C++11新標準中,可以提前聲明enum,該前置聲明必須指定其成員的大小:
enum intValues : unsigned long long //不限定作用域的枚舉必須指定成員類型
enum class open_modes; //限定作用域的枚舉類型因爲有默認的成員類型,所以不用特意指定
和其他聲明一樣,enum的聲明和定義必須匹配,且不能在同一個文件中先聲明一個不限定作用域的enum名字,然後再聲明一個同名的限定作用域的enum。
形參匹配與枚舉類型
初始化一個enum對象時,必須使用另個enum對象或是該枚舉類型的一個枚舉成員,因此,即使某個整型值與枚舉成員的值相等,它也不能作爲函數的enum實參使用:
//不限定作用域的枚舉類型
enum Token{
INLINE = 128,VIRTUAL = 129
};
void f(Token);
void f(int);
int main(){
Token curTok = INLINE;
f(128); //精確匹配的f(int)
f(INLINE); //精確匹配的f(Token)
}
雖然不能將整型值傳給枚舉形參,但是可以將一個不限定作用域的枚舉類型的的對象或枚舉成員傳給整型形參。此時,enum的值轉換爲int或更大的整型,實際轉換的結果由枚舉類型的潛在類型(由機器決定)決定:
void newf(unsigned char);
void newf(int);
unsigned char uc = VIRTUAL;
newf(VIRTUAL); //匹配newf(int)
new(uc); //匹配newf(unsigned char)