列挙型と強く型付けされた列挙型


84

私はC ++プログラミングの初心者です。

今日、私は新しいトピックに出くわします:強くタイプされた enum。私はそれを少し研究しましたが、今まで私はこれが必要な理由と同じものの使用法を見つけることができません。

たとえば、次の場合です。

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

なぜ書く必要があるのですか:

enum class xyz{a, b, c};

ここで何をしようとしていますか?私の最も重要な疑問は、それをどのように使用するかです。私に理解してもらうための小さな例を教えてください。

回答:


114

OK、最初の例:古いスタイルの列挙型には独自のスコープがありません:

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 Coloursenum class Fruits。VS2010でコードを書いたとき。。の"expects a defination or a tag name"下にエラーがスローされclassます。
Rasmi Ranjan Nayak 2012

また、C ++ 98のようなC ++ 11の「通常の」列挙型の場合、デフォルトの基になる型は定義されていません
bruziuz 2015年

2
また、基になる型が指定されている場合は、列挙型の前方宣言を行うことができます。C ++ 11、C ++ 98の通常の列挙型では、許可されていません。Microsoftコンパイラでは、列挙型の前方宣言を行うことができますが、これはMS拡張機能であり、標準ではありません(たとえば、gccでは許可されていません)。したがって、このようなことは合法です。enumForwardDeclare:std :: uint8_t;
bruziuz 2015年

暗黙的に整数型に変換するスコープ付き列挙型を作成できますか?
SSアン

17

このIBMページには列挙型に関する優れた記事があります。非常に詳細でよく書かれています。一言で言えば、いくつかの重要なポイントがあります。

スコープ付き列挙型は、通常の列挙型で発生する制限のほとんどを解決します。完全な型の安全性、明確に定義された基になる型、スコープの問題、前方宣言です。

  • スコープ付き列挙型から他の型への暗黙的な変換をすべて禁止することで、型の安全性を確保します。
  • 新しいスコープを取得すると、列挙型はそれを囲むスコープに含まれなくなり、名前の競合から保護されます。
  • スコープ付き列挙型を使用すると、列挙型の基になる型を指定できます。スコープ付き列挙型の場合、指定しないことを選択すると、デフォルトでintになります。
  • 基になる型が固定されている列挙型は、前方宣言できます。

2
3番目と4番目のポイントは、スコープ付き列挙に固有のものではありません。任意の列挙型の基になる型を指定できます。
マイクシーモア

1
壊れの少ないバージョンのPDFへのリンクを持っている人はいますか?その中のコード例は私のPDFビューアのいずれにもレンダリングされないため、想像力に多くを任せます。
サラシンバック

11

の値enum classは実際には型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);

5

列挙型クラス(「新しい列挙型」、「強力な列挙型」)は、従来のC ++列挙型の3つの問題に対処します。

  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. マッピングシステム固有のエラーコード:In <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 };

これらのいくつかには、==定義済みなどの演算子があります。


3

列挙型スコープ

列挙型は、列挙型を周囲のスコープにエクスポートします。これには2つの欠点があります。まず、同じスコープで宣言された異なる列挙型の2つの列挙子が同じ名前を持っている場合、名前の衝突につながる可能性があります。次に、列挙型名を含む完全修飾名の列挙子を使用することはできません。

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

select = ESet::a; // error
select = a;       // is ambigious
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.