- Lektsia - бесплатные рефераты, доклады, курсовые работы, контрольные и дипломы для студентов - https://lektsia.info -

Байты после перестановки: 0000 1111 0000 0000



В этой программе целочисленной переменной sb.num присваивается число 15. Перестановка двух байтов, составляющих это значение, выполняется путем обмена двух символов, которые образуют массив ch. В результате старший и младший байты целочисленной переменной num меняются местами. Эта операция возможна лишь потому, что как переменная num, так и массив ch разделяют одну и ту же область памяти.

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

// Отображение ASCII-кода символов в двоичной системе счисления.

#include <iostream>

#include <conio.h>

using namespace std;

// Битовые поля, которые будут расшифрованы.

struct byte {

 unsigned a : 1;

 unsigned b : 1;

 unsigned с : 1;

 unsigned d : 1;

 unsigned e : 1;

 unsigned f : 1;

 unsigned g : 1;

 unsigned h : 1;

};

union bits {

 char ch;

 struct byte bit;

}ascii;

void disp_bits(bits b);

Int main()

{

 do {

  cin >> ascii.ch;

  cout << ":";

  disp_bits(ascii);

 }while(ascii.ch!='q'); // Выход при вводе буквы "q".

 return 0;

}

// Отображение конфигурации битов для каждого символа.

void disp_bits(bits b)

{

 if(b.bit.h) cout << "1";

  else cout << "0";

 if(b.bit.g) cout << "1";

  else cout << "0";

 if(b.bit.f) cout << "1";

  else cout << "0 ";

 if(b.bit.e) cout << "1";

  else cout << "0";

 if(b.bit.d) cout << "1";

  else cout << "0";

 if(b.bit.c) cout << "1";

  else cout << "0";

 if(b.bit.b) cout << "1";

  else cout << "0";

 if(b.bit.a) cout << "1";

  else cout << "0";

 cout << "";

}

Вот как выглядит один из возможных вариантов выполнения этой программы.

А: 0 1 1 0 0 0 0 1

B: 0 1 1 0 0 0 1 0

С: 0 1 1 0 0 0 1 1

D: 0 1 1 0 0 1 0 0

Е: 0 1 1 0 0 1 0 1

F: 0 1 1 0 0 1 1 0

G: 0 1 1 0 0 1 1 1

H: 0 1 1 0 1 0 0 0

I: 0 1 1 0 1 0 0 1

J: 0 1 1 0 1 0 1 0

K: 0 1 1 0 1 0 1 1

1: 0 1 1 0 1 1 0 0

M: 0 1 1 0 1 1 0 1

N: 0 1 1 0 1 1 1 0

O: 0 1 1 0 1 1 1 1

P: 0 1 1 1 0 0 0 0

Q: 0 1 1 1 0 0 0 1

Важно! Поскольку объединение предполагает, что несколько переменных разделяют одну и ту же область памяти, это средство предоставляет программисту возможность хранить информацию, которая (в зависимости от ситуации) может содержать различные типы данных, и получать доступ к этой информации. По сути, объединения обеспечивают низкоуровневую поддержку принципов полиморфизма. Другими словами, объединение обеспечивает единый интерфейс для нескольких различных типов данных, воплощая таким образом концепцию "один интерфейс — множество методов" в своей самой простой форме.

Анонимные объединения

Анонимные объединения позволяют объявлять переменные, которые разделяют одну и ту же область памяти.

В C++ предусмотрен специальный тип объединения, который называется анонимным. Анонимное объединение не имеет наименования типа, и поэтому объект такого объединения объявить невозможно. Но анонимное объединение сообщает компилятору о том, что его члены разделяют одну и ту же область памяти. При этом обращение к самим переменным объединения происходит непосредственно, без использования оператора "точка". Рассмотрим такой пример.

//Демонстрация использования анонимного объединения.

#include <iostream>

using namespace std;

Int main()

{

 // Это анонимное объединение.

 union {

  short int count;

  char ch[2];

 };

 // Вот как происходит непосредственное обращение к членам анонимного объединения.

 ch[0] = 'X';

 ch[1] = 'Y';

 cout << "Объединение в виде символов: " << ch[0] <<ch[1] << '';

 cout << "Объединение в виде целого значения: " <<count << '';

 return 0;

}

Эта программа отображает следующий результат.

Объединение в виде символов: XY

Объединение в виде целого значения: 22872


Число 22872 получено в результате помещения символов X и Y в младший и старший байты переменной count соответственно. Как видите, к обеим переменным, входящим в состав объединения, как count, так и ch, можно получить доступ так же, как к обычным переменным, а не как к составляющим объединения. Несмотря на то что они объявлены как часть анонимного объединения, их имена находятся на том же уровне области видимости, что и другие локальные переменные, объявленные на уровне объединения. Таким образом, член анонимного объединения не может иметь имя, совпадающее с именем любой другой переменной, объявленной в той же области видимости.

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

Использование оператора sizeof для гарантии переносимости программного кода

Как было показано, структуры и объединения создают объекты различных размеров, которые зависят от размеров и количества их членов. Более того, размеры таких встроенных типов, как int, могут изменяться при переходе от одного компьютера к другому. Иногда компилятор заполняет структуру или объединение так, чтобы выровнять их по границе четного слова или абзаца. (Абзац содержит 16 байт.) Поэтому, если в программе нужно определить размер (в байтах) структуры или объединения, используйте оператор sizeof. Не пытайтесь вручную выполнять сложение отдельных членов. Из-за заполнения или иных аппаратно-зависимых факторов размер структуры или объединения может оказаться больше суммы размеров отдельных их членов.

И еще. Объединение всегда будет занимать область памяти, достаточную для хранения его самого большого члена. Рассмотрим пример.

union х {

 char ch;

 int i;

 double f;

} u_var;

Здесь при выполнении оператора sizeof u_var получим результат 8 (при условии, что double-значение занимает 8 байт). Во время выполнения программы не имеет значения, что реально будет храниться в переменной u_var; здесь важен размер самой большой переменной, входящей в состав объединения, поскольку объединение должно иметь размер самого большого его элемента.

Переходим к объектно-ориентированному программированию

Эта глава заключает описание не объектно-ориентированных атрибутов C++. Начиная со следующей главы, мы будем рассматривать средства, которые поддерживают объектно-ориентированное программирование (Object Oriented Programming— OOP), или ООП. Чтобы понять объектно-ориентированные средства C++ и научиться их эффективно применять, необходимо глубокое понимание материала этой и предыдущих девяти глав. Поэтому, возможно, вам стоит повторить пройденный материал. Особое внимание при повторении уделите указателям, структурам, функциям и перегрузке функций.


Глава 11: Введение в классы

В этой главе мы познакомимся с классом. Класс — это фундамент, на котором построена С++-поддержка объектно-ориентированного программирования, а также ядро многих более сложных программных средств. Класс — это базовая единица инкапсуляции, которая обеспечивает механизм создания объектов.

Основы понятия класса

Объектно-ориентированное программирование построено на понятии класса.

Начнем с определения терминов класса и объекта. Класс определяет новый тип данных, который задает формат объекта. Класс включает как данные, так и код, предназначенный для выполнения над этими данными. Следовательно, класс связывает данные с кодом. В C++ спецификация класса используется для построения объектов. Объекты — это экземпляры класса. По сути, класс представляет собой набор планов, которые определяют, как строить объект. Важно понимать, что класс — это логическая абстракция, которая реально не существует до тех пор, пока не будет создан объект этого класса, т.е. то, что станет физическим представлением этого класса в памяти компьютера.

Определяя класс, вы объявляете данные, которые он содержит, и код, который выполняется над этими данными. Хотя очень простые классы могут содержать только код или только данные, большинство реальных классов содержат оба компонента. В классе данные объявляются в виде переменных, а код оформляется в виде функций. Функции и переменные, составляющие класс, называются его членами. Таким образом, переменная, объявленная в классе, называется членом данных, а функция, объявленная в классе, называется функцией-членом. Иногда вместо термина член данных используется термин переменная экземпляра (или переменная реализации).

Объявление класса начинается с ключевого слова class.

Класс создается с помощью ключевого слова class. Объявление класса синтаксически подобно объявлению структуры. Рассмотрим пример. Следующий класс определяет тип queue, который предназначен для реализации очереди. (Под очередью понимается список с дисциплиной обслуживания в порядке поступления, т.е. "первым прибыл — первым обслужен".)

// Создание класса queue.

class queue {

  int q[100];

  int sloc, rloc;

 public:

  void init();

  void qput(int i);

  int qget();

};