C++
перечисление
Поиск…
Основная декларация перечисления
Стандартные перечисления позволяют пользователям объявлять полезное имя для набора целых чисел. Названия в совокупности называются счетчиками. Перечисление и связанные с ним счетчики определяются следующим образом:
enum myEnum
{
enumName1,
enumName2,
};
Перечисление - это тип , который отличается от всех других типов. В этом случае имя этого типа - myEnum
. Ожидается, что объекты этого типа будут принимать значение перечислителя в перечислении.
Перечислители, объявленные в перечислении, являются постоянными значениями типа перечисления. Хотя перечисления объявляются внутри типа, оператор области видимости ::
не нужен для доступа к имени. Итак, имя первого enumName1
- enumName1
.
Оператор области может быть необязательно использован для доступа к перечислителю в перечислении. Таким образом, 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 }
с 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; }
или
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 );
Подробный пример с несколькими файлами можно найти здесь: Пример торговца плотными фруктами