为什么人们在 C++ 中使用枚举? 作为常量,同时可以使用 const 吗?

发布于 2024-07-21 05:50:21 字数 42 浏览 5 评论 0原文

当人们可以使用 const 时,为什么在 C++ 中使用枚举作为常量?

Why do people use enums in C++ as constants when they can use const?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

冰魂雪魄 2024-07-28 05:50:21

Bruce Eckel 在 Thinking in C++ 中给出了原因

在旧版本的 C++ 中,类内部不支持 static const。 这意味着 const 对于类内的常量表达式来说是无用的。 然而,人们仍然希望这样做,因此典型的解决方案(通常称为“枚举黑客”)是使用没有实例的未标记的enum。 枚举必须在编译时确定其所有值,它是类的本地值,并且其值可用于常量表达式。 因此,您通常会看到:

#include ; 
  使用命名空间 std; 

  类束{ 
    枚举 { 大小 = 1000 }; 
    int i[大小]; 
  }; 

  int main() { 
    计算<<   “sizeof(束)=”<<   大小(束)  
         <<   ", sizeof(i[1000]) = "  
        <<   sizeof(int[1000]) <<;   结束; 
  } 
  

Bruce Eckel gives a reason in Thinking in C++:

In older versions of C++, static const was not supported inside classes. This meant that const was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untagged enum with no instances. 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;
}
悲凉≈ 2024-07-28 05:50:21

枚举是不同的类型,因此您可以执行面向类型的操作,例如使用它们进行重载:

enum Color { Red,Green,Blue };
enum Size { Big,Little };

void f( Color c ) {
}

void f( Size s ) {
}

int main() {
    f( Red );
    f( Big );
}

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 );
}
静若繁花 2024-07-28 05:50:21

枚举意味着一组相关常量,因此有关关系的附加信息必须在当前问题的模型中有用。

An enumeration implies a set of related constants, so the added information about the relationship must be useful in their model of the problem at hand.

夏日落 2024-07-28 05:50:21

处理模板元编程时也有一个历史原因。 某些编译器可以使用枚举中的值,但不能使用 static const int 来实例化类。

template <int N>
struct foo
{
    enum { Value = foo<N-1>::Value + N };
};

template <>
struct foo<0>
{
    enum { Value = 0; }
};

现在你可以用更明智的方式做到这一点:

template <int N>
struct foo
{
    static const int Value = foo<N-1>::Value + N;
};

template <>
struct foo<0>
{
    static const int Value = 0;
};

另一个可能的原因是 static const int 可能在运行时为其保留内存,而枚举永远不会为其保留实际的内存位置,并且将在编译时间。 请参阅此相关问题。

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.

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. See this related question.

东风软 2024-07-28 05:50:21

我喜欢可以与枚举一起使用的自动行为,例如:

enum {NONE, START, HEY, HO, LAST};

然后很容易循环直到最后,并且当添加新状态(或表示的任何状态)时,逻辑会适应。

for (int i = NONE; i < LAST; i++)
{
    // Do stuff...
}

添加一些东西...

enum {NONE, START, HEY, WEE, HO, LAST};

循环适应...

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.

for (int i = NONE; i < LAST; i++)
{
    // Do stuff...
}

Add something...

enum {NONE, START, HEY, WEE, HO, LAST};

The loop adapts...

绮烟 2024-07-28 05:50:21

使用枚举时更具描述性。 考虑:

int f(int fg, int bg)

 int f(COLOR fg, COLOR bg)

此外,枚举提供了更多的类型安全性,因为

  • 整数不能隐式转换为枚举类型
  • 一种类型的枚举不能隐式转换为另一种类型的枚举

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

  • integers are not implicitly convertible to enum types
  • enum of one type is not implicitly convertible to enum of another type
眼眸里的快感 2024-07-28 05:50:21

在编译器供应商实施 ISO/IEC 14882:1998 C++ 标准之前,在类作用域中定义常量的代码会导致编译错误:

class Foo {
    static const int MAX_LEN = 80;
    ...
};

如果常量是整数类型,则一个笨拙的解决方法是在类范围内的枚举中定义它。班级:

class Foo {
    enum {
        MAX_LEN = 80
    };
    ...
};

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:

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
    };
    ...
};
挽容 2024-07-28 05:50:21

枚举也可以用作类型名称。 因此,您可以定义一个采用枚举作为参数的函数,与将值定义为 const 变量并且函数仅接受“int”相比,这使得更清楚应该将哪些类型的值作为函数的参数给出作为一个论点。

考虑:

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
{
   ...
}

与:

int const baz = 0;
int const meh = 1;

void foo (int bar) // what are valid values for bar?
{
   ...
}

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.

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?
{
   ...
}
超可爱的懒熊 2024-07-28 05:50:21

某些调试器在调试时会显示枚举名称而不是其值。 这非常有帮助。 我知道我宁愿看到 day_of_week = MONDAY 而不是 day_of_week = 1

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.

孤檠 2024-07-28 05:50:21

部分原因是较旧的编译器不支持真正的类常量的声明,

class C
{
  const int ARealConstant = 10;
};

因此必须这样做。

class C
{
  enum { ARealConstant = 10 };
};

因此,许多可移植库继续使用这种形式。

另一个原因是枚举可以用作一种方便的语法设备,将类常量组织成相关的和不相关的常量

class DirectorySearcher
{
  enum options
  {
    showFiles = 0x01,
    showDirectories = 0x02,
    showLinks = 0x04,
  };
};

class Integer
{
   enum { treatAsNumeric = true };
   enum { treatAsIntegral = true };
   enum { treatAsString = false };
};

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 };
};
黑凤梨 2024-07-28 05:50:21

使用枚举以简洁的方式记录有效的选择,并允许编译器强制执行它们。

如果他们使用枚举存储全局常量,例如 Pi,那么我不知道他们的目标是什么。

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.

一生独一 2024-07-28 05:50:21

原因之一是 const 需要更多的输入:

enum { Val1, Val2, Val3 };

...与...

const int Val1=0, Val2=1, Val3=2;

One reason is that const requires more typing:

enum { Val1, Val2, Val3 };

...versus...

const int Val1=0, Val2=1, Val3=2;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文