Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
183
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

(a)int ival = 0; const int *pi =

0;

const int &ri = 0;

(b)pi = &ival; ri = &ival;

pi = &rval;

3.7.Тип bool

// инициализация строки

string search_word = get_word();

// инициализация переменной found bool found = false;

string next_word;

while ( cin >> next_word )

if ( next_word == search_word ) found = true;

//...

//сокращенная запись: if ( found == true )

if ( found )

cout << "ok, мы нашли слово\n";

Объект типа bool может принимать одно из двух значений: true и false. Например: else cout << "нет, наше слово не встретилось.\n";

Хотя bool относится к одному из целых типов, он не может быть объявлен как signed,

// ошибка

unsigned, short или long, поэтому приведенное определение ошибочно: short bool found = false;

Объекты типа bool неявно преобразуются в тип int. Значение true превращается в 1, а

bool found = false;

int occurrence_count = 0;

while ( /* mumble */ )

{

found = look_for( /* something */ );

// значение found преобразуется в 0 или 1

occurrence_count += found;

false – в 0. Например:

}

Таким же образом значения целых типов и указателей могут быть преобразованы в

// возвращает количество вхождений

extern int find( const string& ); bool found = false;

if ( found = find( "rosebud" ))

//правильно: found == true

//возвращает указатель на элемент

extern int* find( int value );

if ( found = find( 1024 ))

значения типа bool. При этом 0 интерпретируется как false, а все остальное как true:

//правильно: found == true

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( "Phoenix_and_the_Crane", append );

Подобное решение допустимо, но не вполне приемлемо, поскольку мы не можем гарантировать, что аргумент, передаваемый в функцию 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, присвоить ей значение одного из

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. Например: