传统的枚举有一些问题。一个是两个不同的枚举的定义可能会产生冲突,看如下两个枚举的定义:
enum egg {Small, Medium, Large, Jumbo};
enum t_shirt {Small, Medium, Large, Xlarge};
如上存在相同的作用域和名称冲突。c++ 11提供了一种新的枚举形式通过为枚举器提供类作用域来避免这个问题。声明形式如下:
enum class egg {Small, Medium, Large, Jumbo};
enum class t_shirt {Small, Medium, Large, Xlarge};
也可以使用关键字struct而不是class,在使用时需要使用枚举数名称来限定枚举数:
egg choice = egg::Large; // the Large enumerator of the egg enum
t_shirt Floyd = t_shirt::Large; // the Large enumerator of the t_shirt enum
既然枚举器具有类作用域,那么枚举器将来自不同的枚举定义不再有潜在的名字冲突。
c++ 11还加强了作用域枚举的类型安全性。常规的枚举在某些情况下,自动将其转换为整数类型,例如枚举被赋值于int变量或用于比较表达式,但作用域枚举没有隐式转换为整数类型:
enum egg_old {Small, Medium, Large, Jumbo}; // unscoped
enum class t_shirt {Small, Medium, Large, Xlarge}; // scoped
egg_old one = Medium; // unscoped
t_shirt rolf = t_shirt::Large; // scoped
int king = one; // implicit type conversion for unscoped
int ring = rolf; // not allowed, no implicit type conversion
if (king < Jumbo) // allowed
std::cout << "Jumbo converted to int before comparison.\n";
if (king < t_shirt::Medium) // not allowed
std::cout << "Not allowed: < not defined for scoped enum.\n";
但是如果你觉得有必要,你可以做一个显式的类型转换:
int Frodo = int(t_shirt::Small); // Frodo set to 0
枚举由某个潜在的整数类型表示,在C98下选择是依赖于实现的。因此,包含枚举的结构
可能在不同的系统上有不同的大小。c++ 11为作用域的枚举消除了这种依赖关系。默认情况下,c++ 11作用域枚举的潜在类型是int,此外,还有一种表示不同选择的语法:
// underlying type for pizza is short
enum class : short pizza {Small, Medium, Large, XLarge};
: short 说明了该枚举的潜在的类型为short,在c++ 11中,您还可以使用这个语法来表示无作用域枚举的类型,但如果不选择类型,则选择编译器生成依赖于实现。
摘自 c++ .primer.plus 6