簡體   English   中英

枚舉vs強類型枚舉

[英]Enum vs Strongly typed enum

我是C ++編程的初學者。

今天,我遇到了一個新話題:強類型enum 我已經研究了一下,但是直到現在我仍無法找出為什么我們需要這個,以及它的用途是什么?

例如,如果我們有:

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

為什么我們需要寫:

enum class xyz{a, b, c};

我們要在這里做什么? 我最重要的疑問是如何使用它。 您能否提供一個小例子,這會讓我理解。

好,第一個示例:舊式枚舉沒有自己的范圍:

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中指定“舊式”枚舉的基礎整數類型。

此IBM頁面上有一篇關於枚舉的很好的文章,它非常詳細且寫得很好。 簡而言之,這是一些重要點:

作用域枚舉解決了常規枚舉所帶來的大多數限制:完整的類型安全性,定義明確的基礎類型,作用域問題和前向聲明。

  • 通過禁止將范圍枚舉的所有隱式轉換為其他類型,可以確保類型安全。
  • 您將獲得一個新的作用域,而該枚舉不再位於封閉的作用域中,從而避免了名稱沖突。
  • 范圍枚舉使您能夠指定枚舉的基礎類型,對於范圍枚舉,如果選擇不指定,則默認為int。
  • 任何具有固定基礎類型的枚舉都可以向前聲明。

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

枚舉類(“新枚舉”,“強枚舉”)解決了傳統C ++枚舉的三個問題:

  1. 傳統的enums隱式轉換為int ,當有人不希望枚舉充當整數時會導致錯誤。
  2. 傳統的enums將其枚舉數導出到周圍的范圍,從而引起名稱沖突。
  3. enum的基礎類型無法指定,從而導致混亂,兼容性問題,並使前向聲明變得不可能。

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

其中一些具有運算符,例如==定義。

枚舉范圍

枚舉將其枚舉數導出到周圍的范圍。 這有兩個缺點。 首先,如果在同一作用域中聲明的不同枚舉中的兩個枚舉器具有相同的名稱,則可能導致名稱沖突; 其次,不可能使用具有完全限定名稱(包括枚舉名稱)的枚舉器。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM