![现代C++编程实战:132个核心技巧示例(原书第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/258/50418258/b_50418258.jpg)
1.6.2 工作原理
无作用域枚举对于开发人员来说会有一些问题:
❍ 它们把枚举器导出到周围的作用域(基于此,它们被称为无作用域枚举),所以就有以下两个缺陷。
a.如果同一命名空间中的两个枚举具有相同名称的枚举器,则可能导致命名冲突。
b.无法使用完全限定名称的枚举器。
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/44_02.jpg?sign=1739698965-PdOpQXfliU57hkSUwzWjRIhQDHA4v7Xz-0-672a1f6c8848b4b9929deea6decbe323)
❍ 在C++11之前,它们没法指定基础类型,必须是整型。类型不能大于int,除非枚举器值不适应有符号或无符号整数。基于此,不能前置枚举声明。原因是枚举的大小是未知的。这是因为在定义枚举器的值之前基础类型是未知的,这样编译器不知道选择哪些合适的整数类型。但是这个问题在C++11中得到了修复。
❍ 枚举器的值会隐式转换为int。这意味着你可以有意或者无意地将有特定含义的枚举和整数混用(这甚至与枚举的含义无关),而且编译器不会发出警告。
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/44_03.jpg?sign=1739698965-ImhYLWSOo6cqpdZJrzsJ1oJqyhR45CtI-0-b4d086080e1e602e2e93f95ba05fb2c5)
作用域枚举基本上是强类型枚举,其行为与无作用域枚举不同:
❍ 它们不会把枚举器导出到周围的作用域。之前提到的两个枚举会变成如下这样,它们不再产生命名冲突并且可以使用完全限定名称的枚举器:
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/44_04.jpg?sign=1739698965-IvmF3iiKUttIJWp5Jji7J9hh8GZw5u6c-0-a8e31324b2134455feadb03db481c3d2)
❍ 可以指定基础类型。除了作用域枚举可以指定基础类型之外,无作用域枚举中基础类型的规则同样适用于作用域枚举。这也解决了前置声明的问题,因为在定义可用之前就已经知道基础类型了:
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/44_05.jpg?sign=1739698965-EoZeGMYbceOrmlJcAvjErnkWz0lhjQLM-0-1103bb94d6379d0ebbb8df48520b42de)
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/45_01.jpg?sign=1739698965-wBdUgLpiIFT6wGFSu0Kpekj84oY7BsFW-0-da9f067855aac0fc4668e0613c0cc157)
❍ 在作用域枚举中,枚举器的值不再隐式地转换为int。除非指定了显式转换,否则将enum class的值赋给整数变量会导致编译错误:
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/45_02.jpg?sign=1739698965-0rttwjvb16m5FxFekcZ0OQTZgh3atLMJ-0-2ded9321d5a76285b81c46c8d79bfd04)
然而,作用域枚举也有缺陷:它们是受限制的命名空间。它们不会把它们的标识符导出到外面的作用域,这一点有时是不方便的。例如,如果你写了一个switch语句,就必须在每个case语句后面重复使用枚举名,下面的例子说明了这一点:
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/45_03.jpg?sign=1739698965-lAtoqu3yQZKtUvfCMQ1374Bk7xaPljUY-0-5228a744411cf9400251e0ffc74569db)
在C++20中,这可以通过使用具有作用域枚举名称的using指令来简化。上述代码可以简化为如下代码:
![](https://epubservercos.yuewen.com/4AD12D/29686922007544106/epubprivate/OEBPS/Images/45_04.jpg?sign=1739698965-jf9UOW0gw58HGnKoulaTRlWQPamcnGCz-0-1919be0d273ad0d8ab56a9c18dd369e1)
using指令的作用是将所有标识符引入局部作用域,这样就可以在不用限定名称的情况下引用它们了。也可以使用using指令将具体的枚举器引入局部作用域,例如using Status::Connected。