Поиск…


Основная декларация перечисления

Стандартные перечисления позволяют пользователям объявлять полезное имя для набора целых чисел. Названия в совокупности называются счетчиками. Перечисление и связанные с ним счетчики определяются следующим образом:

enum myEnum
{
    enumName1,
    enumName2,
};

Перечисление - это тип , который отличается от всех других типов. В этом случае имя этого типа - myEnum . Ожидается, что объекты этого типа будут принимать значение перечислителя в перечислении.

Перечислители, объявленные в перечислении, являются постоянными значениями типа перечисления. Хотя перечисления объявляются внутри типа, оператор области видимости :: не нужен для доступа к имени. Итак, имя первого enumName1 - enumName1 .

C ++ 11

Оператор области может быть необязательно использован для доступа к перечислителю в перечислении. Таким образом, enumName1 также может быть записано myEnum::enumName1 .

Перечислителям присваиваются целочисленные значения, начиная с 0 и возрастая на 1 для каждого перечислителя в перечислении. Таким образом, в приведенном выше случае имя enumName1 имеет значение 0, а значение enumName2 имеет значение 1.

Пользователям также может быть присвоено определенное значение; это значение должно быть интегральным постоянным выражением. Перечисления, значения которых не указаны явно, будут иметь значение, соответствующее значению предыдущего счетчика + 1.

enum myEnum
{
    enumName1 = 1, // value will be 1
    enumName2 = 2, // value will be 2
    enumName3,     // value will be 3, previous value + 1
    enumName4 = 7, // value will be 7
    enumName5,     // value will be 8
    enumName6 = 5, // value will be 5, legal to go backwards
    enumName7 = 3, // value will be 3, legal to reuse numbers
    enumName8 = enumName4 + 2, // value will be 9, legal to take prior enums and adjust them
};

Перечисление в операторах switch

Обычное использование для счетчиков - это для операторов switch, и поэтому они обычно появляются в государственных машинах. На самом деле полезной особенностью операторов switch с перечислениями является то, что если для коммутатора не включен оператор по умолчанию, и не все значения перечисления были использованы, компилятор выдаст предупреждение.

enum State {
    start,
    middle,
    end
};

...

switch(myState) {
    case start:
       ...
    case middle:
       ...
} // warning: enumeration value 'end' not handled in switch [-Wswitch]

Итерация над перечислением

Для перебора не существует встроенного метода.

Но есть несколько способов

  • для enum с только последовательными значениями:

    enum E {
        Begin,
        E1 = Begin,
        E2,
        // ..
        En,
        End
    };
    
    for (E e = E::Begin; e != E::End; ++e) {
        // Do job with e
    }
    
C ++ 11

с enum class , operator ++ должен быть реализован:

E& operator ++ (E& e)
{
    if (e == E::End) {
        throw std::out_of_range("for E& operator ++ (E&)");
    }
    e = E(static_cast<std::underlying_type<E>::type>(e) + 1);
    return e;
}
  • использование контейнера в виде std::vector

    enum E {
        E1 = 4,
        E2 = 8,
        // ..
        En
    };
    
    std::vector<E> build_all_E()
    {
        const E all[] = {E1, E2, /*..*/ En};
        
        return std::vector<E>(all, all + sizeof(all) / sizeof(E));
    }
    
    std::vector<E> all_E = build_all_E();
    

    а потом

    for (std::vector<E>::const_iterator it = all_E.begin(); it != all_E.end(); ++it) {
        E e = *it;
        // Do job with e;
    }
    
C ++ 11
  • или std::initializer_list и более простой синтаксис:

    enum E {
        E1 = 4,
        E2 = 8,
        // ..
        En
    };
    
    constexpr std::initializer_list<E> all_E = {E1, E2, /*..*/ En};
    

    а потом

    for (auto e : all_E) {
        // Do job with e
    }
    

Скопированные перечисления

C ++ 11 вводит так называемые скопированные перечисления . Это перечисления, чьи члены должны быть квалифицированы с enumname::membername . Выделенные области перечислены с использованием синтаксиса enum class . Например, чтобы сохранить цвета в радуге:

enum class rainbow {
    RED,
    ORANGE,
    YELLOW,
    GREEN,
    BLUE,
    INDIGO,
    VIOLET
};

Чтобы получить доступ к определенному цвету:

rainbow r = rainbow::INDIGO;

enum class es не может быть неявно преобразован в int s без приведения. Поэтому int x = rainbow::RED недействителен.

Скопированные перечисления также позволяют указать базовый тип , который является типом, используемым для представления члена. По умолчанию это int . В игре Tic-Tac-Toe вы можете хранить кусок как

enum class piece : char {
    EMPTY = '\0',
    X = 'X',
    O = 'O',
};

Как вы можете заметить, enum может иметь конечную запятую после последнего члена.

Передать декларацию в C ++ 11

Области:

...
enum class Status; // Forward declaration 
Status doWork(); // Use the forward declaration
...
enum class Status { Invalid, Success, Fail };
Status doWork() // Full declaration required for implementation
{
    return Status::Success;
}    

Неперечисленные перечисления:

...
enum Status: int; // Forward declaration, explicit type required
Status doWork(); // Use the forward declaration
...
enum Status: int{ Invalid=0, Success, Fail }; // Must match forward declare type
static_assert( Success == 1 );

Подробный пример с несколькими файлами можно найти здесь: Пример торговца плотными фруктами



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow