枚举值与枚举名称冲突

Kam*_*mek 6 c++ enums gcc

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

namespace Test
{
    enum EName
    {
        CoolEnum,
        NiceEnum
    };

    enum CoolEnum
    {
        CoolVal1,
        CoolVal2
    };

    enum NiceEnum
    {
        NiceVal1,
        NiceVal2
    };
}
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么编译器允许这样的东西.我们来这里是一个代码示例:

Test::CoolEnum cEnum = Test::NiceVal1; // INVALID, as compiler refers to Test::CoolEnum value of Test::Ename enum
Run Code Online (Sandbox Code Playgroud)

为什么会出现这种混乱?我理解为什么我必须在前面加上enum关键字,所以编译器清楚地知道我在声明给定枚举的变量,而不是在同一名称空间中使用其他枚举的值.我只是不明白为什么首先它甚至可以做这样的结构.

mfo*_*ini 8

C++ 11的枚举类是这个的解决方案:

namespace Test
{
    enum class EName
    {
        CoolEnum,
        NiceEnum
    };

    enum class CoolEnum
    {
        NiceVal1,
        NiceVal2
    };

    enum class NiceEnum
    {
        NiceVal1,
        NiceVal2
    };
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用适当的NiceVal1:

Test::CoolEnum cEnum = Test::CoolEnum::NiceVal1;
Run Code Online (Sandbox Code Playgroud)

普通枚举是从C继承的,其中没有命名空间的概念.如果普通枚举引入了某种命名空间,那么使用枚举的C代码根本就不会编译.这就是引入枚举类的原因,以免破坏向后兼容性.

  • 很高兴知道,但这不是给定问题的答案。我很高兴他们在 C++11 中清除了一些东西,但我只是想知道为什么首先这是可能的 (2认同)

Mar*_*k B 1

答案是因为标准规定了这种行为。参见3.3.7/2:

类名 (9.1) 或枚举名称 (7.2) 可以被同一作用域中声明的对象、函数或枚举器的名称隐藏。如果类或枚举名称与对象、函数或枚举器在同一范围内(以任意顺序)以相同名称声明,则无论对象、函数或枚举器名称可见,类或枚举名称都会隐藏。

据推测,这是为了促进与长期以来建立的 C 机制(枚举器不打开新作用域)的兼容性。

在您的情况下,至少使用 g++ 您可以使用它typename来指示您想要使用类型而不是枚举器 ( typename Test::CoolEnum cEnum = Test::NiceVal1;)。

但总的来说,我喜欢将所有枚举范围限制在单独的命名空间或类中,以完全防止这些冲突。