web-dev-qa-db-ja.com

C++で列挙型を使用する方法

次のようなenumがあるとします。

enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};

このenumのインスタンスを作成し、それを適切な値で初期化したいので、次のようにします。

Days day = Days.Saturday;

今私は自分の変数またはインスタンスを既存のenum値でチェックしたいので、私はします:

if (day == Days.Saturday)
{
    std::cout<<"Ok its Saturday";
}

これによりコンパイルエラーが発生します。

エラー:「。」トークンの前に主表現が必要です

明確にするために、言うことの違いは何ですか:

if (day == Days.Saturday)         //Causes compilation error

そして

if (day == Saturday)

この2つは実際には何を表していますか?1つはOKで、もう1つはコンパイルエラーを引き起こしますか?

182
Breeze

このコードは間違っています。

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

なぜならDaysはスコープでもオブジェクトでもないからです。タイプです。そして型自体はメンバーを持っていません。あなたが書いたのはstd::string.clearと同等です。 std::stringは型なので、.を使うことはできません。クラスの instance .を使用します。

残念ながら、列挙型は魔法のようなものであり、その類推はそこで止まります。クラスでは、メンバ関数へのポインタを取得するためにstd::string::clearを実行できますが、C++ 03ではDays::Sundayは無効です。 (これは悲しいです)。これは、C++がCと(やや)後方互換性があり、Cに名前空間がないため、列挙はグローバル名前空間に含まれる必要があるためです。だから構文は単純です:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday)

幸いなことに、 Mike Seymour は、これがC++ 11で対処されたことを確認しています。 enumenum classに変更すると、独自のスコープを取得します。そのためDays::Sundayは有効なだけでなく、Sundayにアクセスするための only の方法です。幸せな日々!

300
Mooing Duck

列挙型変数を宣言して比較するにはこれで十分です。

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
    std::cout << "Ok its Saturday";
}
23

これの多くはコンパイルエラーを与えるはずです。

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

これで、SaturdaySundayなどを最上位のベア定数として使用でき、Daysを型として使用できます。

Days day = Saturday;   // Days.Saturday is an error

同様に後で、テストする:

if (day == Saturday)
    // ...

これらのenum値は裸の定数に似ています-それらはun-scopedです-コンパイラーから少し余分な助けを借りて:(あなたがC++ 11を再使用enumクラス)彼らare n'tカプセル化たとえば、オブジェクトまたは構造体メンバーのように、それらをDaysmembersとして参照することはできません。

enum classを導入する C++ 11 を使用すると、探しているものが得られます。

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

このC++は、いくつかの点でCとは少し異なります。1つは、変数を宣言するときに、Cがenumキーワードを使用する必要があることです。

// day declaration in C:
enum Days day = Saturday;
22
pb2q

あなたが望むようにスコープを使うためのトリックを使うことができます、ちょうどそのような方法でenumを宣言してください:

struct Days 
{
   enum type
   {
      Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday
   };
};

Days::type day = Days::Saturday;
if (day == Days::Saturday)
11
ataman1x

多くのif文を使用するのではなく、enumは文を切り替えるのに適しています。

私は自分のゲーム用に構築しているレベルビルダーでいくつかのenum/switchの組み合わせを使います。

編集:もう一つのこと、私はあなたが似ている構文が欲しいと思う。

if(day == Days.Saturday)
etc

これはC++で実行できます。

if(day == Days::Saturday)
etc

これは非常に簡単な例です。

EnumAppState.h

#ifndef ENUMAPPSTATE_H
#define ENUMAPPSTATE_H
enum eAppState
{
    STARTUP,
    EDIT,
    ZONECREATION,
    SHUTDOWN,
    NOCHANGE
};
#endif

Somefile.cpp

#include "EnumAppState.h"
eAppState state = eAppState::STARTUP;
switch(state)
{
case STARTUP:
    //Do stuff
    break;
case EDIT:
    //Do stuff
    break;
case ZONECREATION:
    //Do stuff
    break;
case SHUTDOWN:
    //Do stuff
    break;
case NOCHANGE:
    //Do stuff
    break;
}
7
Dean Knight

これはC++では機能しません。

Days.Saturday

Daysは、ドット演算子でアクセスできるメンバーを含むスコープまたはオブジェクトではありません。この構文は単なるC#主義であり、C++では無効です。

マイクロソフトは長い間、スコープ演算子を使用して識別子にアクセスできるようにするC++拡張機能を維持してきました。

enum E { A, B, C };

A;
E::B; // works with Microsoft's extension

しかし、これはC++ 11より前の標準ではありません。 C++ 03では、enumで宣言された識別子はenum型自体と同じ有効範囲内にのみ存在します。

A;
E::B; // error in C++03

C++ 11はenum識別子でenum識別子を修飾することを合法にします、そしてまた、それらを周囲のスコープに置く代わりに識別子のための新しいスコープを作成するenumクラスを導入します。

A;
E::B; // legal in C++11

enum class F { A, B, C };

A; // error
F::B;
6
bames53

まだC++ 03を使用していてenumを使用したい場合は、ネームスペース内でenumを使用する必要があります。例えば:

namespace Daysofweek{
enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
}

あなたは、名前空間の外で列挙型を使うことができます、

Daysofweek::Days day = Daysofweek::Saturday;

if (day == Daysofweek::Saturday)
{
    std::cout<<"Ok its Saturday";
}
5
San

厳密に型指定された列挙体 C++ 11 standardで利用可能な機能を探しています。列挙型をスコープ値を持つクラスに変換します。

独自のコード例を使用すると、次のようになります。

  enum class Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
  Days day = Days::Saturday;

  if (day == Days::Saturday)  {
    cout<<" Today is Saturday !"<<endl;
  }
  //int day2 = Days::Sunday; // error ! invalid 

列挙へのアクセサとして::を使用すると、C++ 11より前のC++標準をターゲットとすると失敗します。しかし、古いコンパイラの中にはそれをサポートしていないものもあり、IDEの中にはこのオプションをオーバーライドして古いC++標準を設定するものもあります。

Gccを使用している場合は、 -std = c ++ 11 または -std = gnu11 を指定してC + 11を有効にします。

幸せになる !

4
Alex Byrth

C++のenumは、enum-valuesを宣言するときに、それらが指定した名前でマスクされた整数のようなものです(定義ではなく、動作方法のヒントにすぎません)。

しかし、コードには2つのエラーがあります。

  1. enumすべて小文字のつづり
  2. 土曜日までにDays.は必要ありません。
  3. この列挙型がクラス内で宣言されている場合は、if (day == YourClass::Saturday){}を使用してください。
3
Balázs Édes

残念ながら、列挙型の要素は「グローバル」です。あなたはday = Saturdayをすることによってそれらにアクセスします。つまり、enum A { a, b } ;enum B { b, a } ;は矛盾しているからです。

3
Grzegorz

C++(C++ 11を除く)には列挙型がありますが、その中の値はグローバル名前空間に「リーク」されています。
それらをリークさせたくない(そしてenum型を使う必要がない)のであれば、以下を考慮してください。

class EnumName {  
   public:   
      static int EnumVal1;  
      (more definitions)  
};  
EnumName::EnumVal1 = {value};  
if ([your value] == EnumName::EnumVal1)  ...
2
InitializeSahib

あなたの根本的な問題は.の代わりに::を使うことだと思います。

試してください:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days::Saturday;
if(Days::Saturday == day)  // I like literals before variables :)
{
    std::cout<<"Ok its Saturday";
}
1
James Oravec