Как использовать перечисления в С++

Предположим, что enum имеет следующий вид:

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

Я хочу создать экземпляр этого enum и инициализировать его с помощью правильного значения, поэтому я:

Days day = Days.Saturday;

Теперь я хочу проверить свою переменную или экземпляр с существующим значением enum, поэтому я:

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

Что дает мне ошибку компиляции:

error: ожидаемое первичное выражение перед '. Маркер

Чтобы было ясно, в чем разница между высказыванием:

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

и

if (day == Saturday)

?

На что эти два на самом деле ссылаются, в том, что один ОК, и один вызывает ошибку компиляции?

Ответ 1

Этот код неверен:

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

Потому что Days - это не сфера и не объект. Это тип. И сами типы не имеют членов. То, что вы написали, эквивалентно std::string.clear. std::string является типом, поэтому вы не можете использовать . в теме. Вы используете . на экземпляре класса.

К сожалению, перечисления магические, и аналогия на этом заканчивается. Потому что с классом вы можете сделать std::string::clear чтобы получить указатель на функцию-член, но в C++ 03, Days::Sunday недопустима. (Что грустно). Это потому, что C++ (в некоторой степени) обратно совместим с C, а C не имеет пространств имен, поэтому перечисления должны были находиться в глобальном пространстве имен. Таким образом, синтаксис просто:

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

К счастью, Майк Сеймур отмечает, что это было рассмотрено в C++ 11. Измените enum на enum class и он получит собственную область видимости; поэтому Days::Sunday не только действителен, но и является единственным способом доступа к Sunday. Счастливые дни!

Ответ 2

Этого будет достаточно, чтобы объявить переменную enum и сравнить ее:

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

Ответ 3

В значительной степени это должно привести к ошибкам компиляции.

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

Теперь Saturday, Sunday и т.д. можно использовать как голые константы верхнего уровня, а Days можно использовать как тип:

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

И аналогично позже, чтобы проверить:

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

Эти значения enum похожи на голые константы - они не ограничены областью - с небольшой дополнительной помощью от компилятора: (если вы не используете классы переполнения С++ 11), они не инкапсулируются как объект или например, члены структуры, и вы не можете ссылаться на них как на членов Days.

У вас будет то, что вы ищете, С++ 11, в котором вводится enum class:

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

// ...

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

Обратите внимание, что этот С++ немного отличается от C несколькими способами: один из них - это использование ключевого слова enum при объявлении переменной:

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

Ответ 4

Вы можете использовать трюк для использования областей, как хотите, просто объявите перечисление таким образом:

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

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

Ответ 5

Вместо того, чтобы использовать кучу if-операторов, перечисления хорошо подходят для переключения операторов

Я использую некоторые комбинации enum/switch в построителе уровней, который я создаю для своей игры.

EDIT: Другое дело, я вижу, что вам нужен синтаксис, похожий на;

if(day == Days.Saturday)
etc

Вы можете сделать это в С++:

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

Ответ 6

Это не должно работать на С++:

Days.Saturday

Дни - это не область или объект, который содержит членов, к которым вы можете получить доступ с помощью оператора точки. Этот синтаксис является просто С# -ism и не является законным в С++.

Корпорация Майкрософт уже давно поддерживает расширение С++, которое позволяет вам обращаться к идентификаторам с помощью оператора области:

enum E { A, B, C };

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

Но это нестандартно перед С++ 11. В С++ 03 идентификаторы, объявленные в перечислении, существуют только в той же области, что и сам тип перечисления.

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

С++ 11 разрешает квалифицировать идентификаторы перечислений с именем перечисления, а также вводит классы перечисления, которые создают новую область для идентификаторов вместо размещения их в окружении.

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

enum class F { A, B, C };

A; // error
F::B;

Ответ 7

Если вы все еще используете С++ 03 и хотите использовать перечисления, вы должны использовать перечисления внутри пространства имен. Например:

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

Вы можете использовать перечисление вне пространства имен, например,

Daysofweek::Days day = Daysofweek::Saturday;

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

Ответ 8

Перечисления в С++ похожи на целые числа, замаскированные именами, которые вы им даете, когда вы объявляете свои значения enum (это не определение, а только подсказка, как это работает).

Но в вашем коде есть две ошибки:

  • Заклинание enum все строчные буквы
  • Вам не нужно Days. до субботы.
  • Если это перечисление объявлено в классе, используйте if (day == YourClass::Saturday){}

Ответ 9

К сожалению, элементы перечисления являются "глобальными". Вы обращаетесь к ним, выполняя day = Saturday. Это означает, что у вас не может быть enum A { a, b } ; и enum B { b, a } ;, поскольку они находятся в конфликте.

Ответ 10

В то время как С++ (исключая С++ 11) имеет перечисления, значения в них "просачиваются" в глобальное пространство имен.
Если вы не хотите, чтобы они просочились (и НЕ НУЖНО использовать тип перечисления), рассмотрите следующее:

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

Ответ 11

Вы ищете строго типизированные перечисления, функция, доступная в стандарте C++ 11. Превращает перечисления в классы со значениями области видимости.

Используя ваш собственный пример кода, это:

  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++ до C++ 11. Но некоторые старые компиляторы не поддерживают его, а некоторые IDE просто отменяют эту опцию и устанавливают старый C++ стандарт.

Если вы используете gcc, включите C + 11 с -std = C++ 11 или -std = gnu11.

Будь счастлив !

Ответ 12

Я думаю, что ваша корневая проблема заключается в использовании . вместо ::, который будет использовать пространство имен.

Try:

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

Ответ 13

Прежде всего, сделайте 'E' в перечислении, 'e' в нижнем регистре.

Во-вторых, отмените имя типа "Дни" в "Дни. Суббота".

В-третьих... купите себе хорошую книгу на С++.