枚举vs强类型枚举


84

我是C ++编程的初学者。

今天,我遇到了一个新主题:强类型enum。我已经研究了一下,但是到现在为止我仍无法找出为什么我们需要它,以及它的用途是什么?

例如,如果我们有:

enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/

我们为什么需要写:

enum class xyz{a, b, c};

我们要在这里做什么?我最重要的疑问是如何使用它。您能否提供一个小例子,这会让我理解。

Answers:


114

好,第一个示例:旧式枚举没有自己的范围:

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!

其次,它们隐式转换为整数类型,这可能导致奇怪的行为:

bool b = Bear && Duck; // what?

最后,您可以指定C ++ 11枚举的基础整数类型:

enum class Foo : char { A, B, C};

以前,未指定基础类型,这可能会导致平台之间的兼容性问题。编辑注释中已经指出,您还可以在C ++ 11中指定“旧式”枚举的基础整数类型。


我们需要声明/定义enum class Colours和吗enum class Fruits?因为当我在VS 2010中编写代码时,它"expects a defination or a tag name"在下引发了错误class
Rasmi Ranjan Nayak 2012年

另外:对于C ++ 11中的“普通”枚举,如C ++ 98中的默认默认类型,未定义
bruziuz 2015年

2
另外:如果指定了基础类型,则可以对enum-s进行前向声明。对于C ++ 11,C ++ 98中的普通枚举,不允许使用。Microsoft编译器允许您执行枚举的前向声明,但这只是MS扩展名,不是标准的(例如,gcc不允许这样做),所以现在这样是合法的:
bruziuz 2015年

我们可以限定范围的枚举也隐式转换为整数吗?
SS安妮

17

此IBM页面上有一篇关于枚举的很好的文章,它非常详细且写得很好。简而言之,这是一些重要点:

作用域枚举解决了常规枚举所带来的大多数限制:完整的类型安全性,定义明确的基础类型,作用域问题和前向声明。

  • 通过禁止将范围枚举的所有隐式转换为其他类型,可以确保类型安全。
  • 您将获得一个新的作用域,而该枚举不再位于封闭的作用域中,从而避免了名称冲突。
  • 作用域枚举使您能够指定枚举的基础类型,对于作用域枚举,如果选择不指定,则默认为int。
  • 任何具有固定基础类型的枚举都可以向前声明。

2
第三点和第四点不是特定于范围枚举的。您可以指定任何枚举的基础类型。
Mike Seymour

1
任何人都有指向PDF的较简明版本的链接吗?其中的代码示例未在我的任何PDF查看器中呈现,这让很多人难以想象。
Sara Sinback

11

的值enum class实际上是类型enum class,而不是underlying_typeC枚举。

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);

5

枚举类(“新枚举”,“强枚举”)解决了传统C ++枚举的三个问题:

  1. 传统的enums隐式转换为int,当某人不希望枚举充当整数时会导致错误。
  2. 传统enums上将其枚举器导出到周围的范围,导致名称冲突。
  3. enum无法指定an的基础类型,从而引起混乱,兼容性问题,并使前向声明变得不可能。

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

如图所示,传统枚举可以照常工作,但是您现在可以选择使用枚举的名称进行限定。

新的枚举是“枚举类”,因为它们将传统枚举的各个方面(名称值)与类的各个方面(作用域成员和无转换)结合在一起。

能够指定基础类型允许更简单的互操作性和保证的枚举大小:

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

它还允许枚举的前向声明:

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

基础类型必须是有符号或无符号整数类型之一;默认值为int

在标准库中,enum类用于:

  1. 映射系统特定的错误代码:在<system_error>enum class errc;
  2. 指针安全指标<memory>enum class pointer_safety { relaxed, preferred, strict };
  3. I / O流错误:在<iosfwd>enum class io_errc { stream = 1 };
  4. 异步通信错误处理<future>enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

其中一些具有运算符,例如==defined。


3

枚举范围

枚举将其枚举数导出到周围的范围。这有两个缺点。首先,如果在同一作用域中声明的不同枚举中的两个枚举器具有相同的名称,则可能导致名称冲突;其次,不可能使用具有完全限定名称(包括枚举名称)的枚举器。

enum ESet {a0, a, a1, b1, c3};
enum EAlpha{a, b, c}

select = ESet::a; // error
select = a;       // is ambigious
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.