3.8. ПеречисленияНередко приходится определять переменную, которая принимает значения из некоего
набора. Скажем, файл открывают в любом из трех режимов: для чтения, для записи,
для добавления. const int input = 1; const int output = 2; const int append = 3; и пользоваться этими константами: bool open_file( string file_name, int open_mode); // ... Подобное решение допустимо, но не вполне приемлемо, поскольку мы не можем гарантировать,
что аргумент, передаваемый в функцию open_file() равен только 1, 2 или 3. enum open_modes{ input = 1, output, append }; мы определяем новый тип open_modes. Допустимые значения для объекта этого типа ограничены набором 1, 2 и 3, причем каждое из указанных значений имеет мнемоническое имя. Мы можем использовать имя этого нового типа для определения как объекта данного типа, так и типа формальных параметров функции: void open_file( string file_name, open_modes om ); input, output и append являются элементами перечисления. Набор элементов перечисления задает допустимое множество значений для объекта данного типа. Переменная типа open_modes (в нашем примере) инициализируется одним из этих значений, ей также может быть присвоено любое из них. Например: open_file( "Phoenix and the Crane", append ); Попытка присвоить переменной данного типа значение, отличное от одного из элементов перечисления (или передать его параметром в функцию), вызовет ошибку компиляции. Даже если попробовать передать целое значение, соответствующее одному из элементов перечисления, мы все равно получим ошибку: // ошибка: 1 не является элементом перечисления open_modes open_file( "Jonah", 1 );
open_modes om = input; // ... om = append; open_file( "TailTell", om ); Однако получить имена таких элементов невозможно. Если мы напишем оператор вывода: cout << input << " " << om << endl; то все равно получим: 1 3 Эта проблема решается, если определить строковый массив, в котором элемент с индексом, равным значению элемента перечисления, будет содержать его имя. Имея такой массив, мы сможем написать: cout << open_modes_table[ input ] << " " << open_modes_table[ om ] << endl Будет выведено: input append Кроме того, нельзя перебрать все значения перечисления: // не поддерживается for ( open_modes iter = input; iter != append; ++inter ) // ... Для определения перечисления служит ключевое слово enum, а имена элементов задаются в фигурных скобках, через запятую. По умолчанию первый из них равен 0, следующий – 1 и так далее. С помощью оператора присваивания это правило можно изменить. При этом каждый следующий элемент без явно указанного значения будет на 1 больше, чем элемент, идущий перед ним в списке. В нашем примере мы явно указали значение 1 для input, при этом output и append будут равны 2 и 3. Вот еще один пример: // shape == 0, sphere == 1, cylinder == 2, polygon == 3 enum Forms{ share, spere, cylinder, polygon }; Целые значения, соответствующие разным элементам одного перечисления, не обязаны отличаться. Например: // point2d == 2, point2w == 3, point3d == 3, point3w == 4 enum Points { point2d=2, point2w, point3d=3, point3w=4 }; Объект, тип которого – перечисление, можно определять, использовать в выражениях и передавать в функцию как аргумент. Подобный объект инициализируется только значением одного из элементов перечисления, и только такое значение ему присваивается – явно или как значение другого объекта того же типа. Даже соответствующие допустимым элементам перечисления целые значения не могут быть ему присвоены: void mumble() { Points pt3d = point3d; // правильно: pt2d == 3 // ошибка: pt3w инициализируется типом int Points pt3w = 3; // ошибка: polygon не входит в перечисление Points pt3w = polygon; // правильно: оба объекта типа Points pt3w = pt3d; } Однако в арифметических выражениях перечисление может быть автоматически преобразовано в тип int. Например: const int array_size = 1024; // правильно: pt2w преобразуется intНазад Вперед Содержание |
Нет комментариев. Оставить комментарий: |