
- •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 Значения аргументов функции по умолчанию
Язык C++ позволяет присваивать параметрам функции значения по умолчанию в том случае, когда при вызове функции не указываются параметры. Значения по умолчанию задаются синтаксически сходным образом с инициализацией переменных. Например, ниже объявляется функция f(), имеющая аргументом целую переменную, значением которой по умолчанию является величина 1:
void f(int i = 1);
Теперь функция f() может вызываться двумя способами, как показано ниже:
f(10); // явная передача значения
f(); // функция использует значение по умолчанию
В первом случае аргументу i будет присвоено значение 10. Во втором случае i получит значение по умолчанию, равное 1.
Аргументы по умолчанию в языке C++ позволяют программисту писать более простой код. Для того, чтобы охватывать множество ситуаций, часто функция содержит больше параметров, чем это необходимо при ее наиболее типичном использовании. Используя аргументы по умолчанию, можно указать только аргументы, которые отличаются от значений по умолчанию в каждой конкретной ситуации.
Чтобы лучше представить себе причины использования аргументов по умолчанию, рассмотрим функцию, преобразующая целое число в строку:
char* int_to_string(char *string, int value=999, int base=10)
{
return _itoa(value, string, base);
}
Здесь value – преобразовываемое число, string – буфер для получаемой строки, а base – система счисления, в которой будет представлено число после преобразования в строку.
Следующая короткая программа демонстрирует использование функции int_to_string().
#include <iostream.h>
#include <stdlib.h>
void main()
{
char buffer[20];
cout << int_to_string(buffer, 12345, 16) << “ “; //число 12345 будет представлено в 16-ричной системе счисления
cout << int_to_string(buffer, 12345) << “ “; //число 12345 будет представлено в 10-чной системе счисления (по умолчанию)
cout << int_to_string(buffer) << “\n”; //по умолчанию используется 10-чная система счисления и число 999
return 0;
}
При необходимости использования системы счисления, отличной от десятичной, нужно указать ее явно. В случае использования десятичной системы счисления, ее можно не указывать. Также можно не указывать преобразовываемое число, хотя на практике от этого, скорее всего, не будет большой пользы.
Обратим внимание, что функция int_to_string() вызываются с тремя, двумя или одним аргументом. В случае вызова с одним аргументом величины value и base задаются по умолчанию. При вызове с двумя аргументами величина base задается по умолчанию. Однако невозможно вызвать функцию int_to_string() с величиной value, заданной по умолчанию, и величиной base, заданной при вызове функции. В общем случае при вызове функции ее аргументы совмещаются с соответствующими параметрами слева направо. После того, как всем использованным при вызове функции аргументам поставлены в соответствие параметры, оставшимся аргументам присваиваются их значения по умолчанию.
При создании функции, имеющей аргументы по умолчанию, их значения должны быть указаны только один раз, причем в тот самый момент, когда функция первый раз объявляется в файле. Например, если функция int_to_string() определена после функции main(), то аргументы по умолчанию должны объявляться в прототипе функции int_to_string(), но эти значения больше не должны повторяться при определении функции int_to_string().
Хотя аргументы по умолчанию не могут быть переопределены, при перегрузке функции каждая ее версия может включать в себя новые значения аргументов по умолчанию.
При определении параметров важно понимать, что все параметры по умолчанию располагаются правее параметров, которые не имеют значений по умолчанию. Это означает, что после того, как определен параметр, имеющий значение по умолчанию, нельзя ввести в интерфейсе функции параметр, не имеющий значения по умолчанию. Например, следующее объявление функции int_to_string() является некорректным:
// некорректно!
char* int_to_string(char *string, int value=999, int base);
После того как начались параметры по умолчанию, в списке не могут появиться параметры, не имеющие значения по умолчанию.
Также можно использовать параметры со значениями по умолчанию в конструкторе объекта. В качестве примера ниже приведена новая версия конструктора класса queue:
queue::queue(int id=0)
{
s = r = 0;
who = id;
cout << "Queue " << who << " initialized.\n";
}
В этой версии при объявлении объекта без инициализации каким-либо значением параметр id принимает значение по умолчанию, равное 0. Например, в результате объявления
queue a, b(2);
создаются два объекта - а и b. Значение id для объекта a равно 0, а для объекта b равно 2.