[英]Why do people use enums in C++ as constants while they can use const?
当人们可以使用const
时,为什么人们在 C++ 中使用枚举作为const
?
Bruce Eckel gives a reason in Thinking in C++ : Bruce Eckel 在Thinking in C++ 中给出了一个理由:
In older versions of C++,
static const
was not supported inside classes.在旧版本的 C++ 中,类内部不支持static const
。 This meant thatconst
was useless for constant expressions inside classes.这意味着const
对于类中的常量表达式是无用的。 However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untaggedenum
with no instances.然而,人们仍然希望这样做,因此一个典型的解决方案(通常称为“enum hack”)是使用没有实例的未标记enum
。 An enumeration must have all its values established at compile time, it's local to the class, and its values are available for constant expressions.枚举必须在编译时建立其所有值,它是类的本地值,并且其值可用于常量表达式。 Thus, you will commonly see:因此,您通常会看到:
#include <iostream> using namespace std; class Bunch { enum { size = 1000 }; int i[size]; }; int main() { cout << "sizeof(Bunch) = " << sizeof(Bunch) << ", sizeof(i[1000]) = " << sizeof(int[1000]) << endl; }
Enums are distinct types, so you can do type-oriented things like overloading with them:枚举是不同的类型,因此您可以执行面向类型的操作,例如重载它们:
enum Color { Red,Green,Blue };
enum Size { Big,Little };
void f( Color c ) {
}
void f( Size s ) {
}
int main() {
f( Red );
f( Big );
}
枚举意味着一组相关的常量,因此关于关系的附加信息必须对他们手头问题的模型有用。
There's a historical reason too when dealing with template metaprogramming.在处理模板元编程时也有一个历史原因。 Some compilers could use values from an enum, but not a static const int to instantiate a class.一些编译器可以使用枚举中的值,但不能使用静态 const int 来实例化类。
template <int N>
struct foo
{
enum { Value = foo<N-1>::Value + N };
};
template <>
struct foo<0>
{
enum { Value = 0; }
};
Now you can do it the more sensible way:现在你可以用更明智的方式做到这一点:
template <int N>
struct foo
{
static const int Value = foo<N-1>::Value + N;
};
template <>
struct foo<0>
{
static const int Value = 0;
};
Another possible reason, is that a static const int may have memory reserved for it at runtime, whereas an enum is never going to have an actual memory location reserved for it, and will be dealt at compile time.另一个可能的原因是,静态 const int 可能在运行时为其保留内存,而枚举永远不会为其保留实际内存位置,并将在编译时处理。 See this related question.请参阅此相关问题。
Enums are more descriptive when used.枚举在使用时更具描述性。 Consider:考虑:
int f(int fg, int bg)
versus相对
int f(COLOR fg, COLOR bg)
In addition, enums give a bit more type-safety, because此外,枚举提供了更多的类型安全性,因为
I like the automatic behavior that can be used with enums, for example:我喜欢可以与枚举一起使用的自动行为,例如:
enum {NONE, START, HEY, HO, LAST};
Then it is easy to loop until LAST, and when a new state (or whatever is represented) is added, the logic adapts.然后很容易循环到 LAST,并且当添加新状态(或任何表示的状态)时,逻辑会适应。
for (int i = NONE; i < LAST; i++)
{
// Do stuff...
}
Add something...添点什么...
enum {NONE, START, HEY, WEE, HO, LAST};
The loop adapts...循环适应...
Before compiler vendors implemented the ISO/IEC 14882:1998 C++ standard, this code to define a constant in a class scope resulted in a compile error:在编译器供应商实施 ISO/IEC 14882:1998 C++ 标准之前,这段在类范围内定义常量的代码导致编译错误:
class Foo {
static const int MAX_LEN = 80;
...
};
If the constant is an integer type, a kludgy work around is define it in an enum inside the class:如果常量是整数类型,一个笨拙的解决方法是在类内的枚举中定义它:
class Foo {
enum {
MAX_LEN = 80
};
...
};
enums also can be used as a type name.枚举也可以用作类型名称。 So you can define a function that takes an enum as a parameter, which makes it more clear what kinds of values should be given as arguments to the function, as compared to having the values defined as const variables and the function accepting just "int" as an argument.因此,您可以定义一个将枚举作为参数的函数,与将值定义为 const 变量并且函数仅接受“int”相比,这更清楚应该将哪些类型的值作为函数的参数作为论据。
Consider:考虑:
enum my_new_fangled_type {
baz = 0,
meh = 1
};
void foo (my_new_fangled_type bar) // bar can be a value listed in the enum
{
...
}
versus:相对:
int const baz = 0;
int const meh = 1;
void foo (int bar) // what are valid values for bar?
{
...
}
Some debuggers will show the enumeration name instead of its value when debugging.某些调试器在调试时会显示枚举名称而不是其值。 This can be very helpful.这可能非常有帮助。 I know that I would rather see day_of_week = MONDAY
than day_of_week = 1
.我知道我宁愿看到day_of_week = MONDAY
也不愿看到day_of_week = 1
。
It's partly because older compilers did not support the declaration of a true class constant部分原因是旧的编译器不支持真正的类常量的声明
class C
{
const int ARealConstant = 10;
};
so had to do this所以必须这样做
class C
{
enum { ARealConstant = 10 };
};
For this reason, many portable libraries continue to use this form.出于这个原因,许多便携式库继续使用这种形式。
The other reason is that enums can be used as a convenient syntactic device to organise class constants into those that are related, and those that are not另一个原因是枚举可以作为一种方便的句法工具,将类常量组织成相关的和不相关的。
class DirectorySearcher
{
enum options
{
showFiles = 0x01,
showDirectories = 0x02,
showLinks = 0x04,
};
};
vs对比
class Integer
{
enum { treatAsNumeric = true };
enum { treatAsIntegral = true };
enum { treatAsString = false };
};
Using an enum documents the valid choices in a terse manner and allows the compiler to enforce them.使用枚举以简洁的方式记录有效的选择,并允许编译器强制执行它们。
If they are using enum store global constants, like Pi, for example, then I don't know what their goal is.如果他们使用枚举存储全局常量,例如 Pi,那么我不知道他们的目标是什么。
One reason is that const
requires more typing:原因之一是const
需要更多的输入:
enum { Val1, Val2, Val3 };
...versus... ...相对...
const int Val1=0, Val2=1, Val3=2;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.