【发布时间】:2013-11-08 18:01:53
【问题描述】:
我目前正在考虑命名空间枚举或命名空间静态常量组是否更可取的问题。 什么应该是默认选择,为什么?
选项 1:
namespace Direction
{
enum Direction
{
north,
east,
south,
west,
};
}
选项 2:
namespace Direction
{
static const unsigned char north = 0;
static const unsigned char east = 1;
static const unsigned char south = 2;
static const unsigned char west = 3;
}
两者各有优缺点。
专业枚举:
-
一些类型安全:
void foo(Direction dir); // the compiler won't allow you to just pass an int or a value of an unrelated enum without explicitly casting it
反枚举:
-
类型安全相当有限:
enum A { Entry1 = 1 }; enum B { Entry2 = 10 }; A a; if(a == Entry2) ; // ouch! 不支持除 int 以外的任何其他类型 - 在 C++ 11 之前,不能只拥有例如 long long、short 或 char 的枚举
-
枚举的命名空间不是最理想的
如果不将枚举封装到单独的命名空间中,那么它的所有成员都会污染周围的命名空间。
如果确实将枚举包装到一个单独的命名空间中,那么当使用枚举本身作为一种类型时会得到一些冗余: 然后必须以 Direction::Direction 的方式声明一个方向变量(当不执行“使用 Direction::Direction”时,这将让他们再次污染外部命名空间(最后在代码的那部分,其中使用指令生效)),以便能够以 Direction::north 的方式命名其成员,而不仅仅是北
专业静态常量:
- 在 C++ 11 之前的 C++ 中提供更好的类型支持 - 例如,可以将 unsigned char 等类型用于常量
- 适当的作用域 - 不污染外部命名空间,无需通过 using 指令明确要求(即使在有限的范围内)
对比静态常量:
-
类型安全性甚至比枚举还差 - 再也不能像这样声明函数原型了:
void foo(Direction dir);但必须通过以下方式进行:
void foo(unsigned char dir); // now each variable of type unsigned char or of a type that can implicitly be casted into unsigned char can be passed, even if its totally unrelated to the expected "enumeration" or if the value does not match the value of any of the expected consts
编辑: 在这里,我发现了一篇关于枚举类型安全限制的有趣文章: http://www.drdobbs.com/enumerations/184401797
【问题讨论】:
-
枚举是为此目的,它们不占用内存(如果不使用),并且输入方式更少
-
在您的第二个示例中,
north分配给了什么?使用enum,您可以使用默认值,或者您可以指定应该使用哪个常量值。仅类型检查是值得的。不要做其他选择。 -
我不明白问题的重点。如果您要枚举 事物(例如基本方向)并且您应该具有“类型安全性”,那么请使用
enums。static变量适用于其他一系列问题。 -
@aaronman: afaik 一个静态 const 仅在其地址被引用时才占用内存,否则即使使用它也不占用任何内存。
-
"不支持除 int 以外的任何其他类型 - 在 C++ 11 之前 [...]" 枚举(即使在 C++03 中)是具有未指定的底层类型——这个底层类型不必是
int[dcl.enum]/5:“枚举的底层类型是一个可以表示所有枚举值的整数类型在枚举中定义。由实现定义的整数类型用作枚举的基础类型,除非基础类型不得大于int,除非枚举数的值不能适合int或@ 987654335@。”