在类中声明一个枚举
Posted
技术标签:
【中文标题】在类中声明一个枚举【英文标题】:Declaring an enum within a class 【发布时间】:2011-01-31 00:30:24 【问题描述】:在下面的代码 sn-p 中,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
枚举。这样,至少,我们明确了我们所指的枚举。)
【问题讨论】:
【参考方案1】:我更喜欢以下方法(代码如下)。 它解决了“命名空间污染”问题,但它也更加类型安全(你不能分配甚至比较两个不同的枚举,或者你的枚举与任何其他内置类型等)。
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))
)
一些参考资料:
-
Herb Sutter,Jum Hyslop,C/C++ 用户杂志,22(5),2004 年 5 月
Herb Sutter、David E. Miller、Bjarne Stroustrup 强类型枚举(修订版 3),2007 年 7 月
【讨论】:
我喜欢这个。它还强制使用有效值实例化枚举。我确实认为赋值运算符和复制构造函数会很有用。 t_ 也应该是私有的。我可以不用的宏。 我也喜欢这个。感谢您的参考。 你说:“而且它的类型安全性更高(你不能分配甚至比较两个不同的枚举......”。你为什么认为它是一个好功能?我认为if(c2 == Color::Red )
是合理的,必须编译,但在你的例子中它没有。同样的赋值参数!
@Nawaz c2
是另一种类型 (Color2
),那么您为什么认为 c2 == Color::Red
和作业应该编译?如果Color::Red
是1,而Color2::Red
是2 会怎样? Color::Red == Color2::Red
应该评估为 true
还是 false
?如果你混合使用非类型安全的枚举器,你会很糟糕。
为什么不是类型 t_;私人的?【参考方案2】:
现在 - 使用 C++11 - 你可以使用 enum class 来做这个:
enum class Color RED, BLUE, WHITE ;
AFAII 这正是你想要的。
【讨论】:
遗憾的是,它不允许成员函数:***.com/a/53284026/7395227【参考方案3】:一般来说,我总是将我的枚举放在struct
中。我看过一些指南,包括“前缀”。
enum Color
Clr_Red,
Clr_Yellow,
Clr_Blue,
;
一直认为这看起来更像 C
指南而不是 C++
指南(一方面是因为缩写,也因为 C++
中的命名空间)。
因此,为了限制范围,我们现在有两种选择:
命名空间 结构/类我个人倾向于使用struct
,因为它可以用作模板编程的参数,而不能操作命名空间。
操纵示例包括:
template <class T>
size_t number() /**/
它返回结构体T
中枚举元素的数量:)
【讨论】:
【参考方案4】:如果 Color
是特定于 Car
s 的东西,那么这就是限制其范围的方式。如果您要拥有另一个其他类使用的 Color
枚举,那么您不妨将其设为全局(或至少在 Car
之外)。
没有区别。如果有一个全局的,那么仍然使用本地的,因为它更接近当前范围。请注意,如果您在类定义之外定义这些函数,则需要在函数的接口中显式指定 Car::Color
。
【讨论】:
2.是和不是。Car::Color getColor()
但 void Car::setColor(Color c)
因为在 setColor
我们已经有了说明符。【参考方案5】:
如果您正在创建代码库,那么我将使用命名空间。但是,您仍然只能在该命名空间内拥有一个 Color 枚举。如果您需要一个可能使用通用名称的枚举,但可能对不同的类有不同的常量,请使用您的方法。
【讨论】:
以上是关于在类中声明一个枚举的主要内容,如果未能解决你的问题,请参考以下文章