首先通过两行代码了解,什么是限定作用域的枚举类型,什么是不限作用域的枚举类型。
enum Color{black,white,red}; //不限作用域的枚举类型
enum class Color{black,white,red}; //限定作用域的枚举类型,多了一个class关键字
优先使用限定作用域的枚举类型的原因有三个:
1、降低名字空间污染。防止枚举值名称与变量名冲突。
//不限作用域的枚举类型
enum Color{black,white,red};
auto white = false; //变量white与枚举值white名称冲突
//限定作用域的枚举类型
enum class Color{black,white,red};
auto white = false; //不冲突
2、枚举量是更强类型的,禁止其向其他类型的隐式转换,除非使用static_cast关键字强制类型转换。
//不限作用域的枚举类型
enum Color{black,white,red};
Color c = 1; //可以与整型直接隐式转换
//限定作用域的枚举类型
enum class Color{black,white,red};
Color c = 1; //编译报错,不能直接转换,需要借助static_cast关键字
3、可以直接进行前置声明
enum Color; //不知道底层实现,编译报错,不能进行前置声明
enum class Color; //底层实现默认为int,可以进行前置声明
关于不限作用域的枚举类型不能前置声明的原因,这里简单介绍一下:为了能够表达出不限作用域的枚举类型区间,编译器通常会为枚举类型选用足够表示其区间的类型作为其底层实现,例如,如果枚举值是1~10,那使用short就可以完成,但是这时候又向其中新加了一个值0xFFFFFFFF,那编译器不得不改用long来表示,注意,此时所有使用该枚举值的地方将都会重新编译,所以由于无法知道不限作用域的枚举类型的底层实现,所以也就无法为其分配空间,也就无法前置声明。而限定作用域的枚举类型可以前置声明的原因是,其默认的使用int作为其底层实现。
如果我们在声明时候指定其底层实现,则不限作用域的枚举类型也可以前置声明,例如:
enum Color::int; //指定了底层类型,可以前置声明
enum class Color::int;//同理,限定作用域的枚举类型也可以指定底层类型
要点速记
- C++98风格的枚举型别,现在称为不限作用域的枚举类型,C++11的枚举类型称为限定作用域的枚举类型
- 限定作用域的枚举类型只在枚举型别内可见,它们只能通过static_cast强制类型转换为其他类型
- 限定作用域的枚举类型和不限作用域的枚举类型都支持底层实现型别指定,限定作用域的枚举类型的默认底层型别是int,而不限作用域的枚举类型无默认值
- 限定作用域的枚举类型可以前置声明,而不限定作用域的枚举类型只能在手动指定了底层实现型别后才能前置声明