枚举值与枚举名称冲突
Enum value collision with enum name
让我们以我最近在项目中的某个地方找到的代码结构为例:
namespace Test
{
enum EName
{
CoolEnum,
NiceEnum
};
enum CoolEnum
{
CoolVal1,
CoolVal2
};
enum NiceEnum
{
NiceVal1,
NiceVal2
};
}
我的问题是为什么编译器允许这样的事情。让我们在这里看一个代码示例:
Test::CoolEnum cEnum = Test::NiceVal1; // INVALID, as compiler refers to Test::CoolEnum value of Test::Ename enum
为什么允许这种混乱?我理解为什么我必须在前面加上枚举关键字,所以编译器清楚地知道我正在声明给定枚举的变量,而不是在同一命名空间中使用其他枚举的值。我只是不明白为什么首先甚至可以进行这样的结构。
C++11 的枚举类是解决方案:
namespace Test
{
enum class EName
{
CoolEnum,
NiceEnum
};
enum class CoolEnum
{
NiceVal1,
NiceVal2
};
enum class NiceEnum
{
NiceVal1,
NiceVal2
};
}
然后,您可以使用适当的NiceVal1
:
Test::CoolEnum cEnum = Test::CoolEnum::NiceVal1;
普通枚举是从 C 继承而来的,其中没有命名空间的概念。如果纯枚举引入了某种命名空间,则使用枚举的 C 代码根本不会编译。这就是引入枚举类的原因,以免破坏向后兼容性。
答案是因为标准规定了这种行为。参见 3.3.7/2:
类名 (9.1) 或枚举名 (7.2) 可以通过名称隐藏 在同一作用域中声明的对象、函数或枚举器。如果 类或枚举名称以及对象、函数或枚举器是 在同一范围内(以任何顺序)声明,具有相同的名称, 类或枚举名称隐藏在对象、函数或 枚举器名称可见。
据推测,这是为了促进与 C 的机制(枚举器不会打开新范围)的兼容性,该机制已经建立了很长时间。
在您的情况下,至少使用 g++ 您可以使用 typename
来指示您想要使用类型而不是枚举器 ( typename Test::CoolEnum cEnum = Test::NiceVal1;
)。
但是,一般来说,我喜欢将所有枚举的范围限定在单独的命名空间或类中,以完全防止这些冲突。
相关文章:
- 不带大括号的枚举形式
- 枚举环境变量的惯用C++14/C++17方法
- 类似枚举的计算常量
- 如何正确实现和访问运算符的各种自定义枚举器
- 错误:从"int"到枚举c++的转换无效
- C++中构造函数中的枚举
- 访问在 C++ 结构中声明的枚举变量
- 枚举类'classname'的多重定义
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- typedef 枚举和枚举类有什么区别?
- 在Visual Studio中定义与Typedef枚举发生冲突的原因是什么?
- protobuf-net into .proto 会产生枚举冲突
- 奇怪的枚举名称冲突
- 类名和枚举值之间的冲突:无需命名空间即可解析
- 枚举值与枚举名称冲突
- 基于 SAPI 的应用程序在枚举令牌时引发内存访问冲突
- #define 宏和枚举使用相同的名称导致的冲突
- 全局作用域枚举和命名空间冲突
- 避免预定义的数字常量与c++中的枚举冲突
- 枚举成员与类名冲突