C ++中枚举访问语义背后的基本原理

时间:2012-03-21 22:57:37

标签: c++ enums rationale

有人能否了解一下用于访问C ++中类中定义的枚举的语义?

特别是,为什么枚举成员是通过类的名称而不是枚举本身来访问的?鉴于enum是容器/范围,就像namespaceclass一样,为什么访问容器的元素时处理enum而不是它的时候。一个class

鉴于

namespace mynamespace
{
    class myclass
    {
    public:
        enum myenum
        {
            enum1,
            enum2
        };

        int myint;
    };
}

为什么enum1 mynamespace::myclass::enum1而非mynamespace::myclass::myenum::enum1的完全限定名称?

虽然后者“有效”,但它不是“推荐”的方式来调用它,而一些编译器会在那里发出警告。恕我直言,它不仅应该是正确的,而且它也应该是访问它的唯一方式。

它实现了非常奇怪的访问规则,并且当您在不同的枚举中添加新的enum1时会使事情变得非常奇怪(此时您必须添加限定符)。

真的,它违背了枚举的目的。枚举的成员实际上是更多的成员,而不是枚举,我必须说我发现其他语言(例如C#)的行为更为可取。

我想这是为了保持与C的兼容性,但我不明白为什么要求访问语义中的枚举名称是更好的选择...我想要制作 name optional是保留C兼容性的选项。

2 个答案:

答案 0 :(得分:6)

在C ++ 03中,与在C中一样,enum不会引入新范围。定义的名称将进入周围范围。可能是命名空间或类。

C ++ 11添加了范围内的枚举和基于枚举。

普通C ++ 03 enum

enum Cpp03 { a, b, c };

C ++ 11 基于enum

enum Cpp11Based: long { a, b, c };

C ++ 11 作用域enum (作为名称的作用域,如您的示例所示):

enum class Cpp11Scoped1 { a, b, c };
enum struct Cpp11Scoped2 { a, b, c };

最后两种形式是等效的,并允许写作,例如Cpp11Scoped1::a

最后,范围enum可以基于(为名称指定基础类型,即大小和签名):

enum class Cpp11ScopedAndBased: long { a, b, c };

一些C ++ 03编译器,包括Visual C ++,也为普通的C ++ 03 enum提供了范围功能。

我的猜测是你遇到了什么,语言扩展。

答案 1 :(得分:1)

基本答案是你的“鉴于enum是容器/范围”是完全错误的 - 根据C和C ++,enum 建立范围(而不是容器)。

简而言之,enum whatever { a, b, c};

与以下内容完全不同:

const int a = 0;
const int b = 1;
const int c = 2;

虽然您可以使用enum whatever来定义能够保存该类型值的变量,但它们通常与能够保持正确值范围的某种整数类型完全不同。