[英]Enum vs Strongly typed enum
I am a beginner in C++ programming. 我是C ++编程的初学者。
Today I come across a new topic: strongly typed enum
. 今天,我遇到了一个新话题:强类型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? 我已经研究了一下,但是直到现在我仍无法找出为什么我们需要这个,以及它的用途是什么?
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. 您能否提供一个小例子,这会让我理解。
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. 以前,未指定基础类型,这可能会导致平台之间的兼容性问题。 Edit It 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中指定“旧式”枚举的基础整数类型。
There's a good article about enums at this IBM page , it's very detailed and well-written. 在此IBM页面上有一篇关于枚举的很好的文章,它非常详细且写得很好。 Here are some important points in a nutshell: 简而言之,这是一些重要点:
The scoped enums solve most of the limitations incurred by regular enums: complete type safety, well-defined underlying type, scope issues, and forward declaration. 作用域枚举解决了常规枚举所带来的大多数限制:完整的类型安全性,定义明确的基础类型,作用域问题和前向声明。
Values of enum class
is really of type enum class
, not underlying_type
as for C-enums. enum class
值实际上是enum class
类型,而不是C-enums的underlying_type
。
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);
The enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations: 枚举类(“新枚举”,“强枚举”)解决了传统C ++枚举的三个问题:
enums
implicitly convert to int
, causing errors when someone does not want an enumeration to act as an integer. 传统的enums
隐式转换为int
,当有人不希望枚举充当整数时会导致错误。 enums
export their enumerators to the surrounding scope, causing name clashes. 传统的enums
将其枚举数导出到周围的范围,从而引起名称冲突。 enum
cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible. enum
的基础类型无法指定,从而导致混乱,兼容性问题,并使前向声明变得不可能。 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
类用于:
<system_error>
: enum class errc
; 映射系统特定的错误代码:在<system_error>
: enum class errc
; <memory>
: enum class pointer_safety { relaxed, preferred, strict };
指针安全指示符:在<memory>
: enum class pointer_safety { relaxed, preferred, strict };
<iosfwd>
: enum class io_errc { stream = 1 };
I / O流错误:在<iosfwd>
: enum class io_errc { stream = 1 };
<future>
: enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
异步通信错误处理:在<future>
: enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
Several of these have operators, such as ==
defined. 其中一些具有运算符,例如==
定义。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.