Корректное использование аргументов по умолчанию является мощным средством разработки программ. Однако не исключено его неправильное использование. Аргументы со значениями по умолчанию должны позволять функции выполнять ее задачи эффективно и легко, обеспечивая в то же время значительную гибкость. Для этого значения аргументов по умолчанию должны соответствовать наиболее частому способу использования данной функции. Если не существует одного значения, которое чаще всего соответствует параметру, то нет смысла в использовании аргумента со значением по умолчанию. Фактически объявление в этом случае аргументов со значениями по умолчанию будет вводить в заблуждение всякого, кто читает программу.
При использовании значений аргументов по умолчанию необходимо также учитывать следующее правило: никакое значение аргумента по умолчанию не должно вызывать вредных или разрушительных последствий. Иначе говоря, случайное использование значений аргументов по умолчанию не должно вызывать катастрофы.
В языке C++ расширены возможности структуры, если сравнивать их с языком С. В C++ классы и структуры тесно взаимосвязаны. Фактически, за одним исключением, они взаимозаменяемы, поскольку структура в C++ может включать как данные, так и код, который может манипулировать этими данными таким же образом, как и класс. Структуры также могут содержать конструкторы и деструкторы. Единственное отличие между ними связано с тем, что по умолчанию члены класса имеют в качестве спецификатора доступа private, тогда как спецификатором доступа членов структуры служит public. Согласно формальному синтаксису C++, ключевое слово struct определяет тип класса. В качестве примера рассмотрим структуру:
struct cl
{
int get_i();
void put_i(int j);
private:
int i;
};
int cl::get_i()
{
return i;
}
void cl::put_i(int j)
{
i = j;
}
В большинстве случаев программисты, работающие на языке C++, используют классы для определения объектов, содержащих и данные и код. Они используют структуры для определения объектов, содержащих только данные. Это означает, что структуры используются обычно точно в том же стиле, что и структуры в языке С.
Точно так же, как структуры и классы связаны между собой, связаны и объединения и классы. Объединения представляют по существу структуру, в которой все элементы хранятся в одном и том же месте. Объединения могут содержать конструкторы и деструкторы, а также функции-члены и дружественные функции. Подобно структурам, члены объединения по умолчанию имеют в качестве спецификатора доступа public. Например, следующая программа использует объединение для вывода символов, соответствующих старшему и младшему байтам короткого целого (имеющего размер в два байта как для 16-битных, так и для 32-битных сред):
#include <iostream.h>
union u_type
{
u_type(short int a);
void showchars();
short int i;
char ch[2];
};
u_type::u_type(short int a)
{
i = a;
}
void u_type::showchars()
{
cout << ch[0] << " ";
cout << ch[1] << "\n";
}
int main()
{
u_type u(1000);
u.showchars();
return 0;
}
Важно понимать, что подобно структуре, объявление объединения определяет тип класса. Это означает, что принципы инкапсуляции сохраняют свою силу.
Имеется несколько ограничений, которые необходимо иметь в виду при использовании объединений в C++. Первое — объединение не может наследовать какие-либо другие классы. Далее объединение не может использоваться в качестве базового класса. Объединение не может иметь виртуальные функции-члены. Никакие статические переменные не могут быть членами объединения. Объединение не может иметь в качестве члена какой-либо объект, перегружающий оператор =. Наконец, никакой объект не может быть членом объединения, если этот объект имеет конструктор или деструктор.
Одной из интересных разновидностей объединений в языке C++ является анонимное объединение. Оно не поддерживается в языке С. Анонимное объединение (anonymous union) представляет собой объединение, у которого нет имени или объектов, имеющих это объединение в качестве своего типа. Имена членов этого объединения доступны непосредственно без использования оператора точка или оператора стрелка. Ниже представлен короткий пример, использующий анонимное объединение:
#include <iostream.h>
int main()
{
union
{ // нет имени объединения
int i;
char ch[4];
}; // не указаны переменные
/* обращение к i и ch без ссылки на объединение
и без использования операторов точка или стрелка */
i = 88;
cout << i << " " << ch[0];
return 0;
}
На использование анонимных объединений имеется несколько ограничений. По очевидным причинам имена членов анонимного объединения должны отличаться от всех остальных идентификаторов в области видимости объединения. Это означает, что имена членов объединения не должны конфликтовать с остальными идентификаторами в пределах области видимости объединения. Также глобальные анонимные объединения должны вводиться с ключевым словом static. Анонимные объединения не могут содержать функций-членов. Наконец, анонимные объединения не могут включать частных или защищенных (protected) членов.
Надо помнить, что хотя C++ придает объединениям больше мощи и гибкости, это не означает, что их использование обязательно. В тех случаях, когда достаточно объединения в стиле языка С, можно использовать его именно таким образом. Однако в тех случаях, когда инкапсулируется объединение с процедурами для работы с ним, это придает программе более структурированную форму.