6

让我们看一下我最近在项目某处发现的代码构造:

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

4

2 回答 2

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 代码将根本无法编译。这就是引入枚举类的原因,以免破坏向后兼容性。

于 2012-07-06T14:05:05.347 回答
1

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

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

想必这是为了便于与 C 的机制(枚举器不打开新的作用域)兼容,这种机制已经建立了很长时间。

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

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

于 2012-07-06T15:02:56.763 回答