让我们采用我最近在项目中找到的代码构造:
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
为什么会出现这种混淆?我理解为什么我必须在前面添加enum关键字,所以编译器清楚地知道我在声明给定枚举的变量,而不是在同一名称空间中使用其他枚举的值。我只是不明白为什么首先甚至可以做出这样的结构。
答案 0 :(得分:8)
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代码根本就不会编译。这就是引入枚举类的原因,以免破坏向后兼容性。
答案 1 :(得分:1)
答案是因为标准规定了这种行为。见3.3.7 / 2:
可以通过名称隐藏类名(9.1)或枚举名称(7.2) 在同一范围内声明的对象,函数或枚举器。如果一个 类或枚举名称以及对象,函数或枚举器 在同一范围内(以任何顺序)声明具有相同名称的 类或枚举名称隐藏在对象,函数或的任何位置 枚举器名称可见。
据推测,这是为了促进与已经建立了很长时间的C机制(枚举器不开放新范围)的兼容性。
在您的情况下,至少使用g ++,您可以使用typename
表示您要使用该类型而不是枚举器(typename Test::CoolEnum cEnum = Test::NiceVal1;
)。
一般情况下,我喜欢将所有枚举的范围放在单独的命名空间或类中,以完全防止这些冲突。