// чисто мнимое число: 0 + 7-i
complex double purei( 0, 7 );
// мнимая часть равна 0: 3 + Oi
complex float rea1_num( 3 );
// и вещественная, и мнимая часть равны 0: 0 + 0-i
complex long double zero;
// инициализация одного комплексного числа другим
complex double purei2( purei );
Поскольку complex, как и vector, является шаблоном, мы можем конкретизировать его типами float, double и long double, как в приведенных примерах. Можно также определить массив элементов типа complex:
complex double conjugate[ 2 ] = {
complex double ( 2, 3 ),
complex double ( 2, -3 )
};
Вот как определяются указатель и ссылка на комплексное число:
complex double *ptr = conjugate[0];
complex double ref = *ptr;
Комплексные числа можно складывать, вычитать, умножать, делить, сравнивать, получать значения вещественной и мнимой части. (Более подробно мы будем говорить о классе complex в разделе 4.6.)
3.12. Директива typedef
Директива typedef позволяет задать синоним для встроенного либо пользовательского типа данных. Например:
typedef double wages;
typedef vectorint vec_int;
typedef vec_int test_scores;
typedef bool in_attendance;
typedef int *Pint;
Имена, определенные с помощью директивы typedef, можно использовать точно так же, как спецификаторы типов:
// double hourly, weekly;
wages hourly, weekly;
// vectorint vecl( 10 );
vec_int vecl( 10 );
// vectorint test0( c1ass_size );
const int c1ass_size = 34;
test_scores test0( c1ass_size );
// vector bool attendance;
vector in_attendance attendance( c1ass_size );
// int *table[ 10 ];
Pint table [ 10 ];
Эта директива начинается с ключевого слова typedef, за которым идет спецификатор типа, и заканчивается идентификатором, который становится синонимом для указанного типа.
Для чего используются имена, определенные с помощью директивы typedef? Применяя мнемонические имена для типов данных, можно сделать программу более легкой для восприятия. Кроме того, принято употреблять такие имена для сложных составных типов, в противном случае воспринимаемых с трудом (см. пример в разделе 3.14), для объявления указателей на функции и функции-члены класса (см. раздел 13.6).
Ниже приводится пример вопроса, на который почти все дают неверный ответ. Ошибка вызвана непониманием директивы typedef как простой текстовой макроподстановки. Дано определение:
typedef char *cstring;
Каков тип переменной cstr в следующем объявлении:
extern const cstring cstr;
Ответ, который кажется очевидным:
const char *cstr
Однако это неверно. Спецификатор const относится к cstr, поэтому правильный ответ – константный указатель на char:
char *const cstr;
3.13. Спецификатор volatile
Объект объявляется как volatile (неустойчивый, асинхронно изменяемый), если его значение может быть изменено незаметно для компилятора, например переменная, обновляемая значением системных часов. Этот спецификатор сообщает компилятору, что не нужно производить оптимизацию кода для работы с данным объектом.
Спецификатор volatile используется подобно спецификатору const:
volatile int disp1ay_register;
volatile Task *curr_task;
volatile int ixa[ max_size ];
volatile Screen bitmap_buf;
display_register – неустойчивый объект типа int. curr_task – указатель на неустойчивый объект класса Task. ixa – неустойчивый массив целых, причем каждый элемент такого массива считается неустойчивым. bitmap_buf – неустойчивый объект класса Screen, каждый его член данных также считается неустойчивым.
Единственная цель использования спецификатора volatile – сообщить компилятору, что тот не может определить, кто и как может изменить значение данного объекта. Поэтому компилятор не должен выполнять оптимизацию кода, использующего данный объект.
3.14. Класс pair
Класс pair (пара) стандартной библиотеки С++ позволяет нам определить одним объектом пару значений, если между ними есть какая-либо семантическая связь. Эти значения могут быть одинакового или разного типа. Для использования данного класса необходимо включить заголовочный файл:
#include utility
Например, инструкция
pair string, string author( "James", "Joyce" );
создает объект author типа pair, состоящий из двух строковых значений.
Отдельные части пары могут быть получены с помощью членов first и second:
string firstBook;
if ( Joyce.first == "James"
Joyce.second == "Joyce" )
firstBook = "Stephen Hero";