在下面的代码片段中,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;
};
(1)这是限制Color
枚举范围的好方法吗?或者,我应该在Car
类之外声明它,但可能在它自己的命名空间或结构中声明它?我今天刚刚看到这篇文章,主张后者并讨论关于枚举的一些好点:http://gamesfromwithin.com/stupid-c-tricks-2-better-enums。
(2)在这个例子中,当在类中使用时,最好将枚举编码为Car::Color
,还是仅Color
就足够了? (我假设前者更好,以防万一在全局命名空间中声明了另一个Color
枚举。这样,至少,我们明确指出我们所指的枚举。)
答案 0 :(得分:78)
如果Color
仅限于Car
s,那么这就是限制其范围的方式。如果您要使用其他类使用的其他Color
枚举,那么您也可以将其设为全局(或至少在Car
之外)。
没有区别。如果存在全局值,则仍然使用本地值,因为它更接近当前范围。请注意,如果您在类定义之外定义这些函数,那么您需要在函数的界面中明确指定Car::Color
。
答案 1 :(得分:78)
答案 2 :(得分:62)
我更喜欢以下方法(下面的代码)。 它解决了“命名空间污染”问题,但它更加类型安全(你不能分配甚至比较两个不同的枚举,或你的枚举与任何其他内置类型等)。
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;
};
用法:
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
我创建宏以方便使用:
#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),
用法:
DEFINE_SIMPLE_ENUM(Color,
((Red, 1))
((Green, 3))
)
一些参考文献:
答案 3 :(得分:7)
一般来说,我总是将我的枚举放在struct
中。我看过几个指南,包括“加前缀”。
enum Color
{
Clr_Red,
Clr_Yellow,
Clr_Blue,
};
始终认为这看起来更像C
指南而不是C++
指南(因为缩写而且因为C++
中的命名空间)。
因此,为了限制范围,我们现在有两种选择:
我个人倾向于使用struct
因为它可以用作模板编程的参数,而命名空间不能被操作。
操纵的例子包括:
template <class T>
size_t number() { /**/ }
返回结构T
内的枚举元素数:)
答案 4 :(得分:3)
如果要创建代码库,那么我会使用命名空间。但是,您仍然只能在该命名空间中包含一个Color枚举。如果您需要一个可能使用通用名称但可能具有不同类别的常量的枚举,请使用您的方法。