Читаем Программирование полностью

“Тело” перечисления — это просто список его элементов. Каждому элементу перечисления можно задать конкретное значение, как это сделано выше с элементом jan, или предоставить компилятору подобрать подходящее значение. Если положиться на компилятор, то он присвоит каждому элементу перечисления число, на единицу превышающее значение предыдущего. Таким образом, наше определение перечисления Month присваивает каждому месяцу последовательные значения, начиная с единицы. Это эквивалентно следующему коду:

enum Month {

  jan=1, feb=2, mar=3, apr=4, may=5, jun=6,

  jul=7, aug=8, sep=9, oct=10, nov=11, dec=12

};

Однако это утомительно и открывает много возможностей для ошибок. Фактически мы сделали две опечатки, пока не получили правильный вариант; лучше все же предоставить компилятору делать простую, повторяющуюся, “механическую” работу. Компилятор такие задачи решает лучше, чем люди, и при этом не устает.

Если не инициализировать первый элемент перечисления, то счетчик начнет отсчет с нуля. Рассмотрим такой пример:

enum Day {

  monday, tuesday, wednesday, thursday, friday, saturday, sunday

};

где monday==0 и sunday==6. На практике лучше всего выбирать начальное значение счетчика, равным нулю.

Перечисление Month можно использовать следующим образом:

Month m = feb;

m = 7;     // ошибка: нельзя присвоить целое число перечислению

int n = m; // OK: целочисленной переменной можно присвоить

           // значение Month

Month mm = Month(7); // преобразование типа int в тип Month

                     //(без проверки)

  Обратите внимание на то, что Month — это отдельный тип. Он может быть неявно преобразован в тип int, но неявного преобразования типа Month в тип int не существует. Это имеет смысл, поскольку каждый объект класса Month имеет эквивалентное целое значение, но большинство целых чисел не имеет эквивалентного значения типа Month. Например, мы преднамеренно написали неправильную инициализацию.

Month bad = 9999; // ошибка: целое число невозможно преобразовать

                  // объект типа Month

  Если вы настаиваете на использовании обозначения Month(9999), то сами будете виноваты! Во многих ситуациях язык С++ не пытается останавливать программиста от потенциально опасных действий, если программист явно на этом настаивает; в конце концов, программисту, действительно, виднее.

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

Month int_to_month(int x)

{

  if (x

  return Month(x);

}

Теперь можно написать следующий код:

void f(int m)

{

  Month mm = int_to_month(m);

 // ...

}

Для чего нужны перечисления? В основном перечисление полезно, когда нам нужно множество связанных друг с другом именованных целочисленных констант. Как правило, с помощью перечислений представляют наборы альтернатив (up, down; yes, no, maybe; on, off; n, ne, e, se, s, sw, w, nw) или отличительных признаков (red, blue, green, yellow, maroon, crimson, black).

Обратите внимание на то, что элементы перечисления не входят в отдельную область видимости своего перечисления; они находятся в той же самой области видимости, что и имя их перечисления. Рассмотрим пример.

enum Traffic_sign { red, yellow, green };

int var = red; // примечание: правильно Traffic_sign::red

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже