1.5 枚举类型
简介
C++包含两种枚举:限定作用域和不限定作用域的。C++新标准引入了限定作用域的枚举类型。
1. 限定作用域的枚举类型
enum class open_modes {input, output, append};
// 等价
enum struct open_modes {input, output, append};
2. 不限定作用域的枚举类型
- 省略掉关键字
class
- 枚举名字是可选的
// 不限定作用域的枚举类型
enum color {red, yellow, green};
// 未命名的、不限定作用域的枚举类型
enum {floatPrec = 6, doublePrec = 10, double_doublePrec = 10};
枚举也可以定义新的类型
enum color {red, yellow, green}; // 不限定作用域的枚举类型
enum stoplight {red, yellow, green}; // 错误: 重复定义了枚举成员
enum class peppers {red, yellow, green}; // 正确: 枚举成员被隐藏了
int i = color::red; // 正确: 不限定作用域的枚举类型的枚举成员隐式地转换成int
int j = peppers::red; // 错误: 限定作用域的枚举类型不会进行隐式转换
指定enum的大小
尽管每个enum
都定义了唯一的类型,但是实际上enum
是由某种整数类型表示的。在C++11新标准中,我们可以在enum
的名字后加上冒号以及我们想在该enum
使用的类型:
enum intValues : unsigned long long {
charTyp = 255, shortTyp = 65535, intTyp = 65535,
longTyp = 4394967295UL,
long_longTyp = 18446744073709551615ULLL
};
形参匹配与枚举类型
要想初始化一个enum
对象,必须使用该enum
类型的另一个对象或者它的一个枚举成员。因此,即使某个整型值恰好与枚举成员的值相等,它也不能作为函数的enum
实参使用:
// 不限定作用域的枚举类型,潜在类型因机器而异
enum Tokens {INLINE = 128, VIRTUAL = 129};
void ff(Tokens);
void ff(int);
int main() {
Tokens curTok = INLINE;
ff(128); // 精确匹配ff(int)
ff(INLINE); // 精确匹配ff(Tokens)
ff(curTok); // 精确匹配ff(Tokens)
return 0;
}
尽管我们不能将整型值传递给enum
形参,但是可以将一个不限定作用域的枚举类型的对象或枚举成员传给整型形参。此时enum
的值提升为int
或更大的整型,实际提升的结果由枚举类型的潜在类型决定:
void newf(unsigned char);
void newf(int);
unsigned char uc = VIRTUAL;
newf(VIRTUAL); // 调用newf(int)
newf(uc); // 调用newf(unsigned char)
类内enum值
某些enum值只服务于某个类,我们可以将其声明在类的作用域内,避免污染全局作用域。
#include <iostream>
class Foo {
public:
enum type {
One = 1,
Two,
Three
};
// 其他public成员
private:
// 其他private成员
};
// 使用方法
int main() {
std::cout << Foo::Three << std::endl; // 预期输出3
}
上面这种做法等价于在Foo类中定义常量,实际开发中更通用的是我们可以在Foo声明一个enum类(只有C++11及以上支持):
#include <iostream>
class Foo {
public:
enum class type {
One = 1,
Two,
Three
};
// 其他public成员
private:
// 其他private成员
};
int main() {
Foo::type type = Foo::type::Three;
std::cout << int(type) << std::endl; // 预期输出3
}
编译运行:
$g++ test.cpp -std=c++11 -o test
$./test
3