C++ 枚举 vs 强类型枚举
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12581064/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enum vs Strongly typed enum
提问by Rasmi Ranjan Nayak
I am a beginner in C++ programming.
我是 C++ 编程的初学者。
Today I come across a new topic: strongly typed enum
. I've researched it a bit but till now I am unable to find out why do we need this and what is the use of the same?
今天我遇到了一个新话题:强类型enum
。我已经对它进行了一些研究,但直到现在我无法找出为什么我们需要它以及它的用途是什么?
For example if we have:
例如,如果我们有:
enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/
Why do we need to write:
为什么我们需要写:
enum class xyz{a, b, c};
What are we trying to do here? My most important doubt is how to use it. Could you provide a small example, which will make me understand.
我们在这里想做什么?我最重要的疑问是如何使用它。你能提供一个小例子,这会让我明白。
回答by juanchopanza
OK, first example: old-style enums do not have their own scope:
好的,第一个例子:旧式枚举没有自己的范围:
enum Animals {Bear, Cat, Chicken};
enum Birds {Eagle, Duck, Chicken}; // error! Chicken has already been declared!
enum class Fruits { Apple, Pear, Orange };
enum class Colours { Blue, White, Orange }; // no problem!
Second, they implicitly convert to integral types, which can lead to strange behaviour:
其次,它们隐式地转换为整型,这会导致奇怪的行为:
bool b = Bear && Duck; // what?
Finally, you can specify the underlying integral type of C++11 enums:
最后,您可以指定 C++11 枚举的底层整数类型:
enum class Foo : char { A, B, C};
Previously, the underlying type was not specified, which could cause compatibility problems between platforms. EditIt has been pointed out in comments that you can also specify the underlying integral type of an "old style" enum in C++11.
以前没有指定底层类型,这可能会导致平台之间的兼容性问题。编辑在注释中已经指出,您还可以在 C++11 中指定“旧式”枚举的底层整数类型。
回答by SingerOfTheFall
There's a good article about enums at this IBM page, it's very detailed and well-written. Here are some important points in a nutshell:
在这个 IBM 页面上有一篇关于枚举的好文章,它非常详细且写得很好。简而言之,这里有一些要点:
The scoped enums solve most of the limitations incurred by regular enums: complete type safety, well-defined underlying type, scope issues, and forward declaration.
范围枚举解决了常规枚举带来的大部分限制:完整的类型安全、明确定义的基础类型、范围问题和前向声明。
- You get type safety by disallowing all implicit conversions of scoped enums to other types.
- You get a new scope, and the enum is not anymore in the enclosing scope, saving itself from name conflicts.
- Scoped enums gives you the ability to specify the underlying type of the enumeration, and for scoped enums, it defaults to int if you choose not to specify it.
- Any enum with a fixed underlying type can be forward declared.
- 通过禁止范围枚举到其他类型的所有隐式转换,您可以获得类型安全。
- 您获得了一个新范围,并且枚举不再位于封闭范围内,从而避免了名称冲突。
- 作用域枚举使您能够指定枚举的基础类型,对于作用域枚举,如果您选择不指定它,则默认为 int。
- 任何具有固定基础类型的枚举都可以前向声明。
回答by ForEveR
Values of enum class
is really of type enum class
, not underlying_type
as for C-enums.
的值enum class
实际上是 type enum class
,而不是underlying_type
C 枚举。
enum xyz { a, b, c};
enum class xyz_c { d, f, e };
void f(xyz x)
{
}
void f_c(xyz_c x)
{
}
// OK.
f(0);
// OK for C++03 and C++11.
f(a);
// OK with C++11.
f(xyz::a);
// ERROR.
f_c(0);
// OK.
f_c(xyz_c::d);
回答by Jnana
The enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations:
枚举类(“新枚举”、“强枚举”)解决了传统 C++ 枚举的三个问题:
- conventional
enums
implicitly convert toint
, causing errors when someone does not want an enumeration to act as an integer. - conventional
enums
export their enumerators to the surrounding scope, causing name clashes. - The underlying type of an
enum
cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.
- 常规
enums
隐式转换为int
,当有人不希望枚举充当整数时会导致错误。 - 常规
enums
将其枚举数导出到周围的范围,从而导致名称冲突。 enum
无法指定an 的底层类型,从而导致混淆、兼容性问题,并且无法进行前向声明。
enum class
("strong enums") are strongly typed and scoped:
enum class
(“强枚举”)是强类型和范围的:
enum Alert { green, yellow, orange, red }; // traditional enum
enum class Color { red, blue }; // scoped and strongly typed enum
// no export of enumerator names into enclosing scope
// no implicit conversion to int
enum class TrafficLight { red, yellow, green };
Alert a = 7; // error (as ever in C++)
Color c = 7; // error: no int->Color conversion
int a2 = red; // ok: Alert->int conversion
int a3 = Alert::red; // error in C++98; ok in C++11
int a4 = blue; // error: blue not in scope
int a5 = Color::blue; // error: not Color->int conversion
Color a6 = Color::blue; // ok
As shown, traditional enums work as usual, but you can now optionally qualify with the enum's name.
如图所示,传统枚举照常工作,但您现在可以选择使用枚举名称进行限定。
The new enums are "enum class" because they combine aspects of traditional enumerations (names values) with aspects of classes (scoped members and absence of conversions).
新的枚举是“枚举类”,因为它们将传统枚举的方面(名称值)与类的方面(范围成员和没有转换)结合在一起。
Being able to specify the underlying type allow simpler interoperability and guaranteed sizes of enumerations:
能够指定底层类型允许更简单的互操作性和有保证的枚举大小:
enum class Color : char { red, blue }; // compact representation
enum class TrafficLight { red, yellow, green }; // by default, the underlying type is int
enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E?
// (whatever the old rules say;
// i.e. "implementation defined")
enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // now we can be specific
It also enables forward declaration of enums:
它还启用枚举的前向声明:
enum class Color_code : char; // (forward) declaration
void foobar(Color_code* p); // use of forward declaration
// ...
enum class Color_code : char { red, yellow, green, blue }; // definition
The underlying type must be one of the signed or unsigned integer types; the default is int
.
基础类型必须是有符号或无符号整数类型之一;默认为int
.
In the standard library, enum
classes are used for:
在标准库中,enum
类用于:
- Mapping systems specific error codes: In
<system_error>
:enum class errc
; - Pointer safety indicators: In
<memory>
:enum class pointer_safety { relaxed, preferred, strict };
- I/O stream errors: In
<iosfwd>
:enum class io_errc { stream = 1 };
- Asynchronous communications error handling: In
<future>
:enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
- 映射系统特定的错误代码:In
<system_error>
:enum class errc
; - 指针安全指示器: In
<memory>
:enum class pointer_safety { relaxed, preferred, strict };
- I/O 流错误:在
<iosfwd>
:enum class io_errc { stream = 1 };
- 异步通信错误处理:在
<future>
:enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
Several of these have operators, such as ==
defined.
其中一些具有运算符,例如==
定义的。
回答by Ram
Enum Scope
枚举范围
Enumerations export their enumerators to the surrounding scope. This has two drawbacks. First, it can lead to name clashes, if two enumerators in different enums declared in the same scope have the same name; second, it's not possible to use an enumerator with a fully qualified name, including the enum name.
枚举将其枚举器导出到周围的范围。这有两个缺点。首先,如果在同一作用域中声明的不同枚举中的两个枚举器具有相同的名称,则会导致名称冲突;其次,不可能使用具有完全限定名称的枚举器,包括枚举名称。
enum ESet {a0, a, a1, b1, c3};
enum EAlpha{a, b, c}
select = ESet::a; // error
select = a; // is ambigious