在类中声明枚举

bpo*_*ter 140 c++ enums scope namespaces class

在下面的代码片段中,Color枚举是在Car类中声明的,以便限制枚举的范围并尽量不"污染"全局命名空间.

class Car
{
public:

   enum Color
   {
      RED,
      BLUE,
      WHITE
   };

   void SetColor( Car::Color color )
   {
      _color = color;
   }

   Car::Color GetColor() const
   {
      return _color;
   }

private:

   Car::Color _color;

};
Run Code Online (Sandbox Code Playgroud)

(1)这是限制Color枚举范围的好方法吗?或者,我应该在Car类之外声明它,但可能在它自己的命名空间或结构中声明它?我今天刚刚看到这篇文章,主张后者并讨论关于枚举的一些好点:http: //gamesfromwithin.com/stupid-c-tr​​icks-2-better-enums.

(2)在这个例子中,当类中工作时,最好是将枚举编码为Car::Color,还是只需要Color?(我假设前者更好,以防万一Color在全局命名空间中声明了另一个枚举.这样,至少,我们明确指出我们所指的枚举.)

Pet*_*der 81

  1. 如果Color是特定于Cars的东西,那么这就是限制其范围的方式.如果您打算Color使用其他类使用的另一个枚举,那么您也可以将其设置为全局(或至少在外部Car).

  2. 没什么区别.如果存在全局值,则仍然使用本地值,因为它更接近当前范围.请注意,如果在类定义之外定义这些函数,则需要Car::Color在函数的接口中明确指定.

  • 是的,不是.`Car :: Color getColor()`但是`void Car :: setColor(Color c)`因为在`setColor`中我们已经有了说明符. (12认同)

And*_*ath 80

现在 - 使用C++ 11 - 您可以使用枚举类:

enum class Color { RED, BLUE, WHITE };
Run Code Online (Sandbox Code Playgroud)

AFAII这完全符合您的要求.

  • 可悲的是,它不允许成员函数:/sf/answers/3729881851/ (3认同)

Ser*_*kov 65

我更喜欢以下方法(下面的代码).它解决了"命名空间污染"问题,但它更加类型安全(你不能分配甚至比较两个不同的枚举,或你的枚举与任何其他内置类型等).

struct Color
{
    enum Type
    {
        Red, Green, Black
    };
    Type t_;
    Color(Type t) : t_(t) {}
    operator Type () const {return t_;}
private:
   //prevent automatic conversion for any other built-in types such as bool, int, etc
   template<typename T>
    operator T () const;
};
Run Code Online (Sandbox Code Playgroud)

用法:

Color c = Color::Red;
switch(c)
{
   case Color::Red:
     //????????? ???
   break;
}
Color2 c2 = Color2::Green;
c2 = c; //error
c2 = 3; //error
if (c2 == Color::Red ) {} //error
If (c2) {} error
Run Code Online (Sandbox Code Playgroud)

我创建宏以方便使用:

#define DEFINE_SIMPLE_ENUM(EnumName, seq) \
struct EnumName {\
   enum type \
   { \
      BOOST_PP_SEQ_FOR_EACH_I(DEFINE_SIMPLE_ENUM_VAL, EnumName, seq)\
   }; \
   type v; \
   EnumName(type v) : v(v) {} \
   operator type() const {return v;} \
private: \
    template<typename T> \
    operator T () const;};\

#define DEFINE_SIMPLE_ENUM_VAL(r, data, i, record) \
    BOOST_PP_TUPLE_ELEM(2, 0, record) = BOOST_PP_TUPLE_ELEM(2, 1, record),
Run Code Online (Sandbox Code Playgroud)

用法:

DEFINE_SIMPLE_ENUM(Color,
             ((Red, 1))
             ((Green, 3))
             )
Run Code Online (Sandbox Code Playgroud)

一些参考:

  1. Herb Sutter,Jum Hyslop,C/C++ Users Journal,22(5),2004年5月
  2. Herb Sutter,David E. Miller,Bjarne Stroustrup强类型枚举(修订版3),2007年7月

  • @Nawaz`c2`是另一种类型(`Color2`),所以为什么你认为`c2 == Color :: Red`和赋值应该编译?如果`Color :: Red`为1,而'Color2 :: Red`为2,该怎么办?应该`Color :: Red == Color2 :: Red`评估为`true`还是`false`?如果你混合使用非类型安全的调查员,那你将度过一段美好的时光. (3认同)
  • 为什么不是类型t_; 私人的? (2认同)

Mat*_* M. 7

一般来说,我总是把我的枚举放在一个struct.我看过几个指导方针,包括"前缀".

enum Color
{
  Clr_Red,
  Clr_Yellow,
  Clr_Blue,
};
Run Code Online (Sandbox Code Playgroud)

总是认为这看起来更像是C指导而不是C++(因为缩写而且因为名称空间C++).

因此,为了限制范围,我们现在有两种选择:

  • 命名空间
  • 结构/班

我个人倾向于使用a,struct因为它可以用作模板编程的参数,而命名空间不能被操作.

操纵的例子包括:

template <class T>
size_t number() { /**/ }
Run Code Online (Sandbox Code Playgroud)

返回结构中枚举元素的数量T:)