Остановимся на важном понятии как объединение, которое наряду с классами и структурами часто используется при программировании на С++, кроме того оно очень наглядно демонстрирует мощь объектно-ориентированного программирования. В С++ объединение также определяет тип класса, в котором функции и данные могут содержаться в виде членов. Объединение похоже на структуру тем, что в нем, по умолчанию, все члены открыты до тех пор, пока не используется спецификатор private.
Главное же в том, что в объединении в С++ все данные - члены находятся в одной области памяти. Объединения могут содержать конструкторы и деструкторы. Способность объединений связывать воедино программу и данные позволяет создавать типы данных, в которых все данные используют общую память. Это именно то, чего нельзя сделать, используя классы. Имеется несколько ограничений, накладываемых на использование объединений применительно к С++. Во-первых, они не могут наследовать какой бы то ни было класс, и они не могут использоваться в качестве базового класса для любого другого типа. Объединения не должны содержать объектов с конструктором и деструктором. Рассмотрим пример декларирования объединения в С++:
# include <iostream.h>
union bits
{
bits(double n);
void show_bits();
double d;
}
Здесь показано, что все переменные объединения bits будут занимать одну и ту же область памяти независимо от их типа. При этом будет выполняться операция выравнивания границ под тип, занимающий большее пространство.
Рассмотрим применение и назначение встраиваемых функций. В С++ можно задать функцию, которая, фактически, не вызывается, а ее тело встраивается в программу в месте ее вызова. Преимуществом встраиваемых функций является то, что они не связаны с вызовом функций и механизмом возврата. Это значит, что встраиваемые функции могут выполняться гораздо быстрее обычных. Недостатком встраиваемых функций является то, что если они слишком большие и вызываются слишком часто, объем использующих их программ сильно возрастает. Из-за этого применение встраиваемых функций обычно ограничивается короткими функциями. Для определения встраиваемой функции вписывается спецификатор inline перед определением функции. Рассмотрим сказанное на примере:
# include <iostream.h>
inline int even(int x)
{
return ! (x%2);
}
main()
{
int n;
cin >>n;
if (even(n)) cout << ‘’ число является четным \n’’;
else cout << ‘’ число является нечетным \n’’;
return 0;
}
В этом примере функция even(), которая возвращает истину при четном аргументе, объявлена как встраиваемая функция. Это означает, что строка
if (even(n)) cout << ‘’ число является четным \n’’:
функционально идентична строке:
if (! (10%2)) cout << ‘’ число является четным \n’’;
Этот пример указывает также на другую важную особенность использования встраиваемой функции: она должна быть задана до ее первого вызова. Отметим, что спецификатор inline является запросом, а не командой для компилятора. Очень важно подчеркнуть и то, что некоторые компиляторы не воспринимают функцию как встраиваемую, если она содержит статическую переменную (static), оператор цикла, оператор switch или go to или, если функция является рекурсивной. Если определение функции - члена достаточно короткое, это определение можно включить в объявление класса. Поступив таким образом, мы заставляем, если это возможно, функцию стать встраиваемой. При этом ключевое слово inline не используется. Рассмотрим сказанное на примере:
# include <iostream.h>
class samp
{
int i, j;
public:
samp(int a, int b);
int divisible () { return ! ( i % j );} // определение встраиваемой функции
}
samp :: samp ( int a, int b)
{
i = a;
j = b;
}
main
{
samp ob1 ( 10,2 ), ob2 ( 10,3 );
if ( ob1.devisible()) cout << ‘’ Число делится нацело \n’’;
else cout << ‘’ Число не делится нацело \n’’;
if ( ob2.devisible()) cout << ‘’ Число делится нацело \n’’;