【问题标题】:Access enum values in C++98 and C++11在 C++98 和 C++11 中访问枚举值
【发布时间】:2012-09-12 05:46:19
【问题描述】:

我在“Foo”类(下)中定义了一组枚举值。

namespace Fii
{
    class Foo 
    {
        struct Bar
        {
            enum Baz
            {
                BAZ1,
                BAZ2, 
                BAZ3
            };
        };
    };
};

我正在使用结构来缩小 Baz 枚举值的范围,并显示有一组相关值。

我的目标是将枚举类型中的值分配给变量。使用上面的类定义,可以做到这一点:

Fii::Foo::Bar::Baz myValue = Fii::Foo::Bar::BAZ1 (Works in both C++98 and C++11)

但是,我觉得:

  • 乍一看,myValue 似乎被初始化为 Fii::Foo::Bar 但这只是因为枚举是对父(Bar 在这种情况下)

为了提高准备,我将代码重构为:

namespace Fii
{
    class Foo 
    {
        enum Baz
        {
            BAZ1,
            BAZ2, 
            BAZ3
        };
    };
};

使用这个新的类定义,可以做到这一点:

Fii::Foo::Baz myValue = Fii::Foo::Baz::BAZ1 (Works in C++11 only)
Fii::Foo::Baz myValue = Fii::Foo::BAZ1 (Should work on C++98 and C++11 - not tested)

Q1) 为什么 Fii::Foo::Bar::Baz myValue = Fii::Foo::Baz::BAZ1 只适用于 C++11?

Q2) 在 C++98 中,有没有办法编写 Fii::Foo::Baz myValue = Fii::Foo::Baz::BAZ1 ?您可以在类定义中进行任何您喜欢的更改。

环境: - 支持 C++11 的 Clang 编译器 - Xcode 4 - Mac OS 10.8

【问题讨论】:

    标签: c++ enums c++11 c++98


    【解决方案1】:

    C++11 增加了class enums。它还添加了一种访问旧式枚举值的新方法,这就是您在此处看到的。

    enum Foo { FOO1, FOO2, FOO3 }; // old-style enum
    
    Foo f1 = Foo::FOO1; // OK in C++11, error in C++98.
    Foo f2 = FOO1; // OK in C++98 and C++11 (for backward compatibility)
    

    【讨论】:

      【解决方案2】:

      juanchopanza 的答案对第一季度有效...

      Q2:在 C++98 中,有没有办法写 Fii::Foo::Baz myValue = Fii::Foo::Baz::BAZ1 ?您可以在类定义中进行任何您喜欢的更改。

      类似:

      namespace Fii
      {
          class Foo
          {
              class Baz
              {
                public:
                  enum E { BAZ1, BAZ2, BAZ3 };
                  Baz(E e) : e_(e) { }
                  operator const E() const { return e_; }
                private:
                  E e_;
              };
          };
      }
      

      解释:Fii::Foo::Baz::BAZ1 要成为对 C++03 中枚举的有效引用,Baz 必须namespaceclass/struct/@987654327 @。但是,我们试图让它看起来好像 Baz 本身就是枚举类型,而 BAZ1 是可用值之一。为此,我们必须使 Baz 成为能够存储在其范围内声明的任何枚举的用户定义类型(类/结构)。因此,我们添加了一个数据成员来记录当前值、一个构造器来设置值、一个运算符来隐式地公开枚举值,这样您就不需要在代码中的任何地方使用 @ 显式引用 e_ 987654329@ 对象或调用一些get() const 函数。

      【讨论】:

      • 你能解释一下为什么需要这段代码吗? Baz(E e) : e_(e) { } operator const E() const { return e_; } 私人:E e_;
      • @DavidAndreoletti:在上面的代码中,Baz 是一个“用户定义的类型”——一个其对象实例各自管理一个 E 值的类。您之后询问的代码是存储枚举之一的构造函数,该运算符在对象出现在编译器不知道如何处理Baz 的表达式中时隐式提供E 值,以及存储E 的成员变量。明白了吗? - 随时要求进一步澄清/示例....
      • 我试过你的建议,效果很好。你认为这有助于代码的可读性并且不会妨碍代码的可维护性吗?
      • @DavidAndreoletti:通常使用枚举而不在它们自己的范围内明确分组(即使用Fii::Foo::BAZ1而不是Fii::Foo::Baz::BAZ1)是实用的,但随着Fii::Foo中标识符数量的增加更有可能发生冲突,因此不得不选择不太直观的标识符或添加硬编码的前缀或后缀来对枚举进行分组。与命名空间一样,您可以在任何一方犯错,良好的判断力来自经验和理解因素,如代码易变性、协调、暴露和访问客户端代码。
      • @DavidAndreoletti:例如,如果 Fii::Foo 是您的公司命名空间(不是类),它可能会在由不同团队控制的许多标头中被破坏,几乎没有协调,并直接暴露给您不使用的客户端代码甚至不知道存在。您不希望您的新标识符与其他团队发生冲突,并且可能希望强制客户端明确限定他们正在使用的枚举枚举。在另一个极端,如果枚举在你的私有实现文件中,而你只是发送二进制文件,那么很难修复冲突或耦合的可能性很小。
      猜你喜欢
      • 2020-07-30
      • 2020-05-22
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      相关资源
      最近更新 更多