Основы программирования на С++ для начинающих

Перечисления в С++ (enum)

Перечисления (enum) используются в C++ для создания констант. Допустим надо объявить константы для музыкальных нот и каждую инициализировать соответствующим порядковым номером. Можно воспользоваться уже знакомым нам способом:

перечисления с++, перечисления c++, enumeration c++, enum c++

Такое объявление занимает много строк кода и не совсем удобно. Используя перечисление, можно определить эти константы иным способом. Синтаксис enum похож на синтаксис структур: ключевое слово – дескриптор – элементы в фигурных скобках через запятую :

перечисления с++, перечисления c++, enumeration c++, enum c++

Это полная форма – с дескриптором (именем перечисления). Как и в случае со структурами, имя перечисления можно не использовать:

перечисления с++, перечисления c++, enumeration c++, enum c++

В первом случае – мы сможем создавать переменные типа перечисления  notes. Во втором случае – нет.

Обратите внимание, что значение 1 было присвоено только первому элементу перечисления. По умолчанию первому элементу в фигурных скобках присваиваются значение 0, второму на единицу больше (1), третьему на единицу больше второго (2) и т.д. Но если явно задать значение, как в примере, то увеличение на единицу начнется с этого числа. Покажем на экран значения некоторых элементов перечисления.

В консоли отобразится:перечисления с++, перечисления c++, enumeration c++, enum c++

Хоть мы и не присваивали явно значения RE и SOL  – они хранят правильные порядковые номера нот.

Имена перечислителей (элементов перечисления) должны быть уникальными. Значения же могут совпадать:

 Значение 1 будут хранить KLICHKO_VITALIY и KLICHKO_VLADIMIR. 2 запишется в CHISORA, 3 – в ADAMEK . В элементы перечисления могут быть записаны только целые числа. Изменить ниже в программе значения, которые присвоены элементам в фигурных скобках нельзя. Если создается переменная типа перечисления – она может принять значение только одного из своих элементов:

перечисления с++, перечисления c++, enumeration c++, enum c++

На картинке видно, что записать число в переменную типа champions возможности нет. Можно записать только именованную константу, которая объявлена во время определения enum.

Для закрепления рассмотрим пример. В нём создадим перечисление levelsName. Оно будет содержать шесть элементов – “названия” этажей. Пользователю предложим  “покататься” на лифте.

Объявляем целочисленную переменную floor в строке 10 и инициализируем ее именованной константой parking. Так floor примет значение 0. В строке 13 входим в цикл while. Пока пользователь не введет в переменную exitOrNot значение 0, программа будет ему предлагать “кататься на лифте” – выбрать номер этажа.

После каждого выбора этажа звучит сигнал (три коротких гудка) и на экран выводится номер этажа и информация о том, что на нём размещено. Это реализовано оператором выбора switch. Его блоки case перебирают элементы перечисления. То есть пользователь вводит целое число, а case  ищет, какому из элементов перечисления оно соответствует.

Например, если введено 5 –  это соответствует значению элемента Restaurant – на экран выводится  соответствующее сообщение.

Результат:

перечисления с++, перечисления c++, enumeration c++, enum c++

Посмотрите короткое видео о перечислениях C++. 

7 thoughts on “Перечисления в С++ (enum)

  1. Нормальные примеры, а статью не читал.

    Я сформулирую, а ты поправь пожалуйста, если со статьей я разойдусь в чем-то.

    1) Магические числа – это плохо, чтобы избавиться от них используют константы.

    2) Константы – это хорошо, но константы сильно связаны друг с другом.

    Пример: в программе у нас есть юнит. Юнит может быть магом, гоблином или эльфом. Одним из вариантов реализации этого могло быть что-то такое:

    const int Mag = 1;
    const int Goblin = 2;
    const int Elf = 3;

    struct Unit {
    string name;
    int unit_type;
    };

    Очевидно, это плохо, потому что:
    2.1) константы Mag, Goblin, Elf доступны всем, т.е. засоряют пространство имен;
    2.2) константы могут быть случайно использованы в неправильном контексте, ведь они не сгруппированы, т.е. ничем не отличаются от других констант;
    2.3) полю unit_type можно присвоить неправильное значение (компилятор не сообщит нам об ошибке) :
    unit.unit_type = -123;
    2.4) нам надо придумывать самим значения константам и следить чтобы они не повторялись.

    Все эти проблему эротично решает enum:

    enum UnitType { Mag, Goblin, Elf };
    struct Unit {
    unit_type type;
    string name;
    };

    обратиться к константам мы можем как напрямую (Mag) так и по имени перечисления (UnitType::Mag). Второй вариант обозначает явно контекст, но вроде бы появился в С++11 (раньше его поддерживало большинство компиляторов, но стандарту вроде как оно не соответствовало).

    unit.unit_type = 123;
    завершится ошибкой на этапе компиляции (т.е. очень рано). А если вы юзаете современную IDE – то еще раньше (среда разработки подчеркнет ошибку).

    Ну и значения им присвоены автоматически, следить за этим не надо.

    Код можно сделать чуть красивей:
    struct Unit {
    unum Type {Mag, Goblin, Elf} type;
    string name;
    };

    Это может быть лучше, т.к. видно, что Unit и Type неразрывно связаны (раньше мы кодировали это в имени UnitType). Кодировать что-то в имени не очень хорошо, например если бы Unit переименовали бы в Item – то нам пришлось бы переименовывать ItemType, или связь стала бы не очевидна.
    Unit::Type::Mag лаконично задает контекст, в котором может использоваться константа.

  2. Мой вариант решения задачки из примера:
    pre class=”lang:c++ decode:true ”

    #include
    using namespace std;

    int main()
    {
    setlocale(LC_ALL, “rus”);
    enum lewels {undParking = -1, oneFloor = 1, secondFloor = 2, Restaurant = 3, Penthaus = 4};
    int lift = 0;
    int exit = 1;
    cout <<"Вы зашли в здание и сейчас находитесь на " << oneFloor << " этаже \n";
    do
    {
    cout <> lift;
    switch (lift)
    {
    case(undParking):
    cout << "Вы попали в подземную автостоянку \n";
    break;
    case(oneFloor):
    cout << "Вы на первом этаже \n";
    cout <> exit;
    if (exit == 0)
    {
    cout << "Вы вышли из здания \n";
    }
    break;
    case(secondFloor):
    cout << "Вы на втором этаже \n";
    break;
    case(Restaurant):
    cout << "Вы в ресторане \n";
    break;
    case(Penthaus):
    cout << "Вы в пентхаусе \n";
    break;
    default:
    cout << "Нет такого этажа \n";
    }
    } while (exit == 1);
    return 0;
    }

    /pre

  3. Перечисления в языке C++ прямо наследуют поведение перечислений языка C, за исключением того, что перечисляемый тип в C++ — настоящий тип, и ключевое слово

    1. Цитата из описания языков C и C++:
      > В версии С89 определено 32 ключевых слова.
      > …
      > enum — Пользовательский тип данных “перечисляемый тип”
      > …
      > В языке C++ содержатся все ключевые слова, определенные в версии С89, а также следующие.

      И где здесь различие?

  4. Если для каждого случая перечисления задано значение (известное как значение “raw”), это значение может быть строкой, символом или значением любого целого числа или типа с плавающей запятой.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *