Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
38
Добавлен:
16.04.2013
Размер:
82.43 Кб
Скачать

Объединения

Объединение (union) – это производный тип, синтаксис которого такой же, как и у структур, за исключением того, что ключевое слово union заменяет struct. Члены объединения совместно используют память, и их знанения перекрываются. То есть объявление объединения позволяет интерпретировать его значение как набор типов входящих в него членов. Объединение инициализируется значением в фигурных скобках, причем оно присваивается первому члену объединения. Рассмотрим следующее объявление:

union int_dbl {

int i;

double x;

} n= {0}; // член i инициализован нулем

Переменная n может использоваться или как целая, или как переменная с двойной точностью.

n. i = 7; // в n хранится целое значение 7

cout << n. i << “целое.”;

cout << n. x << “двойной точности – зависит от машины.”;

n. x = 7.0; // значение с двойной точностью

// в n хранится 7.0

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

Объединение может быть безымянным, как в следующем фрагменте:

enum week { sun, mon, tues, weds, thurs, fri, sat } ;

// дни недели

union {

int i;

week w;

};

i = 5;

if (w = = sat | | w = = sun) // суббота или воскресенье

cout << “Выходной! “ ;

Объявление безымянного объединения позволяет использовать идентификаторы отдельных членов как переменные. Имена членов должны быть уникальными в пределах области видимости; кроме того, никакие другие переменные безымянного типа объявлять нельзя. Отметьте, что безымянное объединение, объявленное в области видимости файла, должно быть статическим (static).

Усовершенствуем стек, переделав его в виде объединения различных типов. Суть в том, что стек является структурой данных, полезной для хранения значений любых типов. Такой стек можно использовать для обработки разнородных значений, применяя метод LIFO:

// Стек, усовершенствованный для хранения многих типов

enum type { int_type, dbl_type, chr_type, str_type } ;

union rainbow {

int i;

double x;

char c;

char* p;

};

struct rbdata {

type t;

rainbow d;

};

struct u_stack {

rbdata s [max_len];

int top;

};

Структура данных u_stack более гибкая, за что приходится расплачиваться дополнительной памятью, которая требуется для хранения переменной t типа type для каждого из элементов. Операции стека кодируются так же, как в ch_stack. Например, push ( ):

void push (u_stack* stk, str [i++])

{

stk -> s [++stk -> top = c;

}

При использовании u_stack член t отслеживает, значение какого типа содержится в каждом элементе стека. В случае с разнородными данными, вероятно, подошли бы операторы switch, как в следующем примере:

rdata x;

u_stack * pa;

. . . . . . .

x = pop (pa);

switch (x. t) { // извлечение значения правильного типа

case int_type:

v = x. d. i; // v – целое

break ;

case dbl_type:

y = x. d. i; // y – двойной точности

break ;

. . . . . .

}

Однако такой подход неуклюж и ведет к ошибкам. Неточность в задании t приведет к трудно определяемым ошибкам на этапе выполнения. ООП – средства С++ представляют ряд возможностей, которые позволяют делать те же вещи более удобным и безопасным способом.

Множество научных вычислений нуждается в комплексных числах. Напишем АТД для комплексных чисел.

struct complex {

double real, imag;

};

void assign (complex* pc, double r, double i = 0.0)

{

pc -> real = r;

pc -> imag = i;

}

complex add (complex a, complex b)

{

complex temp;

temp. real = a. real + b. real;

temp. imag = a. imag + b. imag;

return temp;

}

Обратите внимание, что если задан аргумент по умолчанию, то можно присвоить значение с двойной точностью комплексной переменной. В этом случае мнимая часть принимается равной нулю.

В следующем фрагменте складываются действительное и комплексное числа:

double f = 2.5;

complex w, x, z;

assign (&x, 5.5, -3.2); // x = 5.5 – 3.2i

assign (&w, f); // w = 2.5 – 0i

z = add (w, x); // z = 8.0 – 3.2i

В упражнениях с 7 по 9 на стр. 126 вы дополните пакет для работы с комплексными числами другими элементами. Традиционный подход, приведенный выше, неудовлетворителен тем, что не позволяет использовать обычную запись выражения для задания вычисления, такую как

z = f + w; // ООП допускает перегрузку +

Полный набор возможностей ООП допускает естественную запись кода.

Соседние файлы в папке Тельминов (мб)