
- •1.2 Философские замечания
- •1.3 Процедурное программирование
- •1.4 Модульное программирование
- •1.5 Абстракция данных
- •1.6 Пределы абстракции данных
- •1.7 Объектно-ориентированное программирование
- •1.8 Концепции объектно-ориентированного программирования
- •1.8.1 Инкапсуляция
- •1.8.2 Полиморфизм
- •1.8.3 Наследование
- •1.10 Несколько полезных советов
- •2.2 Перегрузка функций
- •2.3 Перегрузка операторов
- •2.4 Наследование
- •2.5 Конструкторы и деструкторы
- •2.7 Два новых типа данных
- •Глава 3. Классы и объекты
- •3.1 Параметризованные конструкторы
- •3.2 Дружественные функции
- •3.3 Значения аргументов функции по умолчанию
- •3.3.1 Корректное использование аргументов по умолчанию
- •3.4 Взаимосвязь классов и структур
- •3.5 Связь объединений и классов
- •3.6 Анонимные объединения
- •3.7 Inline-функции
- •3.7.1 Создание inline-функций внутри класса
- •3.8 Передача объектов в функции
- •3.9 Возвращение объектов функциями
- •3.10 Присваивание объектов
- •3.11 Конструктор копирования
- •3.12 Массивы объектов
- •3.12.1 Инициализация массивов объектов
- •3.12.2 Создание инициализированных и неинициализированных массивов
- •3.13 Указатели на объекты
- •3.14 Статические члены класса
- •Глава 4. Перегрузка функций и операторов
- •4.1 Перегрузка конструкторов
- •4.2 Локализация переменных
- •4.3 Локализация создания объектов
- •4.4 Перегрузка функций и неопределенность
- •4.5 Определение адреса перегруженной функции
- •4.6 Указатель this
- •4.7 Перегрузка операторов
- •4.8 Дружественная функция-оператор
- •4.9 Ссылки
- •4.9.1 Параметры-ссылки
- •4.9.2 Передача ссылок на объекты
- •4.9.3 Возврат ссылок
- •4.9.4 Независимые ссылки
- •4.9.5 Использование ссылок для перегрузки унарных операторов
- •4.10 Перегрузка оператора []
- •4.11 Создание функций преобразования типов
- •Глава 5. Наследование, виртуальные функции и полиморфизм
- •5.1 Наследование и спецификаторы доступа
- •5.1.1 Спецификаторы доступа
- •5.1.2 Спецификатор доступа при наследовании базового класса
- •5.1.3 Дополнительная спецификация доступа при наследовании
- •5.2 Конструкторы и деструкторы производных классов
- •5.3 Множественное наследование
- •5.4 Передача параметров в базовый класс
- •5.5 Указатели и ссылки на производные типы
- •5.6 Ссылки на производные классы
- •5.7 Виртуальные функции
- •5.8 Для чего нужны виртуальные функции?
- •5.9 Чисто виртуальные функции и абстрактные типы
- •5.10 Виртуальный базовый класс
- •5.11 Раннее и позднее связывание
- •Глава 6. Подсистема динамического выделения памяти
- •6.1 Введение в обработку исключений
- •6.1.1 Перехват всех исключений
- •6.2 Работа с памятью с помощью new и delete
- •6.3 Размещение объектов
- •6.4 Перегрузка new u delete
- •7.1.1 Потоки
- •7.3 Создание собственных операторов вставки и извлечения
- •7.3.1 Создание операторов вставки
- •7.3.2 Перегрузка операторов извлечения
- •7.4 Форматирование ввода/вывода
- •7.4.1 Форматирование с помощью функций-членов класса ios
- •7.4.2 Использование манипуляторов
- •7.5 Создание собственных функций-манипуляторов
- •7.5.1 Создание манипуляторов без параметров
- •7.5.2 Создание манипуляторов с параметрами
- •7.6 Файловый ввод/вывод
- •7.6.1 Открытие и закрытие файлов
- •7.6.2 Чтение и запись в текстовые файлы
- •7.6.3 Двоичный ввод/вывод
- •7.6.4 Определение конца файла
- •7.6.5 Произвольный доступ
- •Глава 8. Ввод/вывод в массивы
- •8.1 Классы ввода/вывода в массивы
- •8.2 Создание потока вывода
- •8.3 Ввод из массива
- •8.4 Использование функций-членов класса ios
- •8.5 Потоки ввода/вывода в массивы
- •8.6 Произвольный доступ в массив
- •8.7 Использование динамических массивов
- •8.8 Манипуляторы и ввод/вывод в массив
- •8.9 Собственные операторы извлечения и вставки
- •8.10 Форматирование на основе массивов
- •Глава 9. Шаблоны и библиотека stl
- •9.1 Функции-шаблоны
- •9.2 Функции с двумя типами-шаблонами
- •9.3 Ограничения на функции-шаблоны
- •9.4 Классы-шаблоны
- •9.5 Пример с двумя типами-шаблонами
- •9.6 Обзор библиотеки stl
- •9.7 Класс vector
- •9.7 Класс string
- •9.8 Класс list
3.3.1 Корректное использование аргументов по умолчанию
Корректное использование аргументов по умолчанию является мощным средством разработки программ. Однако не исключено его неправильное использование. Аргументы со значениями по умолчанию должны позволять функции выполнять ее задачи эффективно и легко, обеспечивая в то же время значительную гибкость. Для этого значения аргументов по умолчанию должны соответствовать наиболее частому способу использования данной функции. Если не существует одного значения, которое чаще всего соответствует параметру, то нет смысла в использовании аргумента со значением по умолчанию. Фактически объявление в этом случае аргументов со значениями по умолчанию будет вводить в заблуждение всякого, кто читает программу.
При использовании значений аргументов по умолчанию необходимо также учитывать следующее правило: никакое значение аргумента по умолчанию не должно вызывать вредных или разрушительных последствий. Иначе говоря, случайное использование значений аргументов по умолчанию не должно вызывать катастрофы.
3.4 Взаимосвязь классов и структур
В языке 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++, используют классы для определения объектов, содержащих и данные и код. Они используют структуры для определения объектов, содержащих только данные. Это означает, что структуры используются обычно точно в том же стиле, что и структуры в языке С.
3.5 Связь объединений и классов
Точно так же, как структуры и классы связаны между собой, связаны и объединения и классы. Объединения представляют по существу структуру, в которой все элементы хранятся в одном и том же месте. Объединения могут содержать конструкторы и деструкторы, а также функции-члены и дружественные функции. Подобно структурам, члены объединения по умолчанию имеют в качестве спецификатора доступа 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++. Первое — объединение не может наследовать какие-либо другие классы. Далее объединение не может использоваться в качестве базового класса. Объединение не может иметь виртуальные функции-члены. Никакие статические переменные не могут быть членами объединения. Объединение не может иметь в качестве члена какой-либо объект, перегружающий оператор =. Наконец, никакой объект не может быть членом объединения, если этот объект имеет конструктор или деструктор.