C++. Бархатный путь. Часть 2 - Объединения

ОГЛАВЛЕНИЕ

 

 

Объединения

Мы возвращаемся к объединениям. Наш уровень знаний делает знакомство с этой конструкцией приятным и лёгким.

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

  • объединение может включать функции-члены, в том числе конструкторы и деструкторы. Они, безусловно, могут быть полезны для обслуживания единственного значения объекта-представителя объединения;
  • объединение не может иметь базовых классов и само также не может служить базовым классом. По этой причине в объединения не могут входить виртуальные функции (они бесполезны);
  • объединения также не могут включать статические данные-члены, объекты-представители некоторого класса со специально объявленными конструкторами, деструкторами, операторными функциями присваивания. Всё это служит помехой компактному сохранению значений.

Неименованное объединение определяет объект, а не объявляет тип. Имена членов безымянного объединения должны отличаться от других имён из области действия, где было объявлено это объединение. Безымянное объединение не содержит объявления функций-членов.

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

Этот раздел мы завершим примером, который раскрывает неожиданные возможности использования объединения. Сочетание объединения с битовым полем позволит нам убедиться в корректности преобразований дробной части вещественного числа. Здесь самое время обратиться к соответствующему приложению.

#include <iostream.h>
union
{
float floatVal;
struct
{
int bit0 : 1;
int bit1 : 1;
int bit2 : 1;
int bit3 : 1;
int bit4 : 1;
int bit5 : 1;
int bit6 : 1;
int bit7 : 1;
int bit8 : 1;
int bit9 : 1;
int bit10 : 1;
int bit11 : 1;
int bit12 : 1;
int bit13 : 1;
int bit14 : 1;
int bit15 : 1;
int bit16 : 1;
int bit17 : 1;
int bit18 : 1;
int bit19 : 1;
int bit20 : 1;
int bit21 : 1;
int bit22 : 1;
int bit23 : 1;
int bit24 : 1;
int bit25 : 1;
int bit26 : 1;
int bit27 : 1;
int bit28 : 1;
int bit29 : 1;
int bit30 : 1;
int bit31 : 1;
} BitField;
} MyUnion;
void main ()
{
MyUnion.BitField.bit31 = 0;
MyUnion.BitField.bit30 = 1;
MyUnion.BitField.bit29 = 0;
MyUnion.BitField.bit28 = 0;
MyUnion.BitField.bit27 = 0;
MyUnion.BitField.bit26 = 0;
MyUnion.BitField.bit25 = 1;
MyUnion.BitField.bit24 = 1;
MyUnion.BitField.bit23 = 0;
MyUnion.BitField.bit22 = 0;
MyUnion.BitField.bit21 = 1;
MyUnion.BitField.bit20 = 1;
MyUnion.BitField.bit19 = 0;
MyUnion.BitField.bit18 = 0;
MyUnion.BitField.bit17 = 1;
MyUnion.BitField.bit16 = 0;
MyUnion.BitField.bit15 = 0;
MyUnion.BitField.bit14 = 0;
MyUnion.BitField.bit13 = 1;
MyUnion.BitField.bit12 = 0;
MyUnion.BitField.bit11 = 0;
MyUnion.BitField.bit10 = 0;
MyUnion.BitField.bit9 = 0;
MyUnion.BitField.bit8 = 0;
MyUnion.BitField.bit7 = 0;
MyUnion.BitField.bit6 = 0;
MyUnion.BitField.bit5 = 0;
MyUnion.BitField.bit4 = 0;
MyUnion.BitField.bit3 = 0;
MyUnion.BitField.bit2 = 0;
MyUnion.BitField.bit1 = 0;
MyUnion.BitField.bit0 = 0;
cout << MyUnion.floatVal << endl;
}