Язык программирования C++ для профессионалов



           

Структуры и объединения


По определению структура - это класс, все члены которого общие, т.е. описание

struct s { ...

это просто краткая форма описания

class s { public: ...

Поименованное объединение определяется как структура, все члены которой имеют один и тот же адрес. Если известно, что в каждый момент времени используется значение только одного члена структуры, то объявив ее объединением, можно сэкономить память. Например, можно использовать объединение для хранения лексем транслятора С:

union tok_val { char* p; // строка char v[8]; // идентификатор (не более 8 символов) long i; // значения целых double d; // значения чисел с плавающей точкой };

Проблема с объединениями в том, что транслятор в общем случае не знает, какой член используется в данный момент, и поэтому контроль типа невозможен. Например:

void strange(int i) { tok_val x; if (i) x.p = "2"; else x.d = 2; sqrt(x.d); // ошибка, если i != 0 }

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

tok_val val1 = 12; // ошибка: int присваивается tok_val tok_val val2 = "12"; // ошибка: char* присваивается tok_val

Для правильной инициализации надо использовать конструкторы:

union tok_val { char* p; // строка char v[8]; // идентификатор (не более 8 символов) long i; // значения целых double d; // значения чисел с плавающей точкой

tok_val(const char*); // нужно выбирать между p и v tok_val(int ii) { i = ii; } tok_val(double dd) { d = dd; } };

Эти описания позволяют разрешить с помощью типа членов неоднозначность при перегрузке имени функции. Например:

void f() { tok_val a = 10; // a.i = 10 tok_val b = 10.0; // b.d = 10.0 }

Если это невозможно (например, для типов char* и char[8] или int и char и т.д.), то определить, какой член инициализируется, можно, изучив инициализатор при выполнении программы, или введя дополнительный параметр. Например:

tok_val::tok_val(const char* pp) { if (strlen(pp) <= 8) strncpy(v,pp,8); // короткая строка else p = pp; // длинная строка }




Содержание  Назад  Вперед