【问题标题】:Namespace level enums in c++C ++中的命名空间级别枚举
【发布时间】:2011-11-04 06:34:23
【问题描述】:

直接在命名空间级别使用 c++ 中的枚举是一种不好的做法吗?我的意思是不与任何课程相关联?假设我有一个枚举和一个看起来像这样的类,

enum Player { USER, COMPUTER}

class Game {
//Logic of the game.
};

那么我应该将 Player 枚举声明为游戏类的成员吗?它应该是私有的吗?

【问题讨论】:

    标签: c++ coding-style enums


    【解决方案1】:

    使用 C++11

    这个答案最初是在 2011 年编写的。现在 C++11 支持已广泛使用,首选方法是使用 enum class,正如 Matthew D. Scholefield 在下面指出的那样:

    enum class Player {
        User,
        Computer
    };
    

    枚举常量在引用时必须使用枚举名称进行限定(例如,Player::Computer)。

    C++11 之前

    不,公开的枚举本身并没有错。但是请记住,枚举常量不能用封闭枚举类型的名称来限定。也就是说,你不能写Player::USER或类似的来引用USER常量;它们直接出现在封闭的命名空间中。因此,为常量设置前缀可能是个好主意,这样就不会发生名称冲突。

    例如,考虑以下声明:

    enum Player {
      PL_USER,
      PL_COMPUTER
    }
    

    这样更安全,因为带有“PL_”前缀的名称冲突的可能性要小得多。此外,它通过提示给定常量属于哪个枚举来提高代码可读性。

    C# 和 Java 等语言对枚举采用了稍微不同的方法,其中必须同时指定枚举的名称和常量的名称,例如 Player.USER。在 C++ 中可以通过将枚举声明嵌入到它自己的命名空间中来实现类似的效果。例如:

    namespace Player {
      enum Type {
        USER,
        COMPUTER
      }
    }
    

    这具有将PLAYERCOMPUTER 嵌入Player 命名空间而不是全局(或以其他方式封闭)命名空间的效果。在我看来,这是否是一个好方法是一个偏好问题。

    【讨论】:

    • 而不是两个字符的神秘前缀,考虑例如struct Player { enum Enum{ user, computer }; };。在一两年内,随着编译器开始支持 C++11 特性,这可能是不必要的。但在那之前...无论如何,为宏保留 ALL UPPERCASE 是个好主意。很多人都这样做。
    • @AlfP.Steinbach 我同意。但是,我倾向于使用命名空间而不是结构来封装枚举,因为引入命名空间不会向系统引入任何新类型。
    • @Martin:我更喜欢struct 正是因为它引入了一种类型。这非常方便(例如,您可以继承它)。一个类型不使用内存或任何东西:它是零成本。
    • 请注意,将enum 放在namespacestruct 中不仅将常量的名称放在命名空间或结构中,而且还放在类型的名称中。所以如果客户端代码要声明该类型的变量,他必须写Player::Type,而不仅仅是Type。如果你有 C++11,你可以使用enum class Type 将枚举常量放入枚举本身的范围内(并禁止自动转换为int)。
    【解决方案2】:

    通常对任何事情都使用最小范围。这样更容易理解。

    但是,由于将 enum 放置在班级内部或外部而导致的清晰度或缺乏,与 大喊 相比,使用 ALL UPPERCASE IDENTIFIERS。为宏保留那些。在 Java 中,它们用于常量,因为 Java 的外观和感觉来自 C,在 C 中将常量定义为宏并不罕见(因为早期的 C 没有const)。

    请注意,Java 没有预处理器,也没有宏。采用源自 C 的约定,将宏保存在单独的“命名空间”中,并在不理解其他内容的情况下将其应用于其他内容,从而与最初的意图完全交叉,这有点愚蠢。

    【讨论】:

    • @kmac:C++ 的基本语法直接来自 C,而不仅仅是外观。 C++ 对它进行了扩展和改变,按照当时 C 的传统,这也是非常变化的。在早期的 C 中,创建者经常使用小写的宏名称。你可以看到它的痕迹,例如asserterrno 等等。随着时间的流逝和经验的积累,大写约定演变为占主导地位。但这是为了尽量减少宏的名称冲突。 Java 没有宏,并采用了在C 中定义常量的约定。这种用法在 C++ 中是无关紧要的。
    【解决方案3】:

    如果使用enum Player ...

    • 就在class Game之内-->放在私有范围内
    • class Game 及其子类使用 --> 放入受保护范围
    • 相关class Game并在各个地方使用-->把 在公共范围内
    • Game 无关 --> 放入全局/命名空间范围

    【讨论】:

      【解决方案4】:

      这纯粹是一个偏好问题;但是,我倾向于在 C++ 中使用类似 Java 的枚举:

      class PlayerType {
        public:
           enum VALUE {USER, COMPUTER};
           explicit PlayerType(VALUE val) : value_(val) {}
      
           operator VALUE() const { return value_; }
           bool operator==(VALUE other) const { return value_ == other; }
           bool operator!=(VALUE other) const { return value_ != other; }
        private:
           VALUE value_;
           // Copy and assign intentionally allowed.
      };
      

      我倾向于这样做的原因是,以后需要添加额外的功能(例如与字符串表示形式之间的转换)并不少见,因此这种结构使其易于扩展。

      【讨论】:

        【解决方案5】:

        如果它只在Game 类中使用,我会将枚举放入其中。

        【讨论】:

          【解决方案6】:

          最好在命名空间中定义枚举

          【讨论】:

            猜你喜欢
            • 2014-09-07
            • 2011-10-28
            • 2019-07-22
            • 2023-03-30
            • 1970-01-01
            • 2012-10-18
            • 2014-04-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多