枚举值与枚举名称冲突

时间:2012-07-06 14:02:27

标签: c++ gcc enums

让我们采用我最近在项目中找到的代码构造:

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关键字,所以编译器清楚地知道我在声明给定枚举的变量,而不是在同一名称空间中使用其他枚举的值。我只是不明白为什么首先甚至可以做出这样的结构。

2 个答案:

答案 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;)。

一般情况下,我喜欢将所有枚举的范围放在单独的命名空间或类中,以完全防止这些冲突。