2012-03-21 54 views
2

有人可以阐明访问在C++类中定义的枚举的语义吗?在C++中枚举访问语义背后的理由

特别是,为什么enum成员通过类的名称而不是enum本身访问?假设enum是容器/范围,就像namespaceclass一样,为什么访问容器中的某个元素时,它的处理方式与enum的处理方式不同,而不是class

鉴于

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

     int myint; 
    }; 
} 

为什么是enum1mynamespace::myclass::enum1,而不是mynamespace::myclass::myenum::enum1完全合格的名字吗?

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

它使真正奇怪的访问规则,当你在一个不同的枚举中添加一个新的enum1(在这一点上你必须添加限定符),这使得事情变得很奇怪。

真的,它打败了枚举的目的。枚举的成员实际上比这些枚举的更多成员,我必须说我发现其他语言(例如C#)的行为更可取。

我想这是为了保持与C的兼容性,但我不明白为什么需要访问语义中的枚举名称将是更好的选择...我想象使名称可选将是保留C兼容性的选项。

+0

我认为这是与C兼容,但如果应该考虑使用一个'enum类'它被添加到C++ 11他们服从正确的语义' – 111111 2012-03-21 23:04:31

回答

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

我的猜测是,你遇到了,一个语言的扩展。

+0

你撞到了那里的头上。我最初使用VC++进行范围设定,但一直在做一些“正确”的方法来避免警告,我没有注意到它在GCC(我目前使用的)上的表现有所不同。 – 2012-03-22 00:21:44

+0

只是注意:正确的语法是'枚举类EnumName:int'不'枚举类:INT EnumName' – 2012-03-22 00:27:00

+0

@ MahmoudAl-Qudsi:谢谢!我将编辑答案(其语法不正确)。我从头开始写这篇文章,我认为我没有一个接受这种语法的编译器,尽管我认为最新版本的g ++确实支持它,也可能是clang支持它。 – 2012-03-22 00:41:27

1

最基本的答案是,你的“鉴于enum是集装箱/范围”是完全错误的 - 按照C和C++中,enum建立一个范围(而不是容器)。

总之,enum whatever { a, b, c};

是不是一大堆不同:

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

虽然可以使用enum whatever定义能举行这种类型的值的变量,他们不是一般与能够保持正确范围的值的整数类型完全不同。

+0

只是一个读者的注意事项 - @杰里我知道你知道这一点:一个区别是在C++中,没有从例如的隐式转换“int”枚举值(但有另一种方式)。 – 2012-03-21 23:15:53