- •Базовое ядро языка Элементы программы.
- •Комментарии
- •Инструкция – выражение
- •Инструкция
- •Определение функции
- •Заголовок функции
- •Прототипы функций
- •Аргументы по умолчанию.
- •Перегрузка функций
- •Встраиваемые функции
- •Стек до блока Вошли в блок Вышли из блока
- •Индексирование
- •Int a [100]; одномерный массив
- •Int b [3][5]; двухмерный массив
- •Int c [7][9][2]; трехмерный массив
- •Передача массивов функциям
- •Объявления ссылок и вызовов по ссылке
- •Функции-члены класса
- •Доступ: закрытый и открытый
- •Область видимости класса
- •Оператор разрешения области видимости ::
- •Вложенные классы
- •Статические члены данных
- •Указатель this
- •Функции-члены типа static и const.
- •Изменчивость (mutable)
- •Создание и уничтожение объектов
- •Классы с конструкторами
- •Конструкторы как преобразования
- •Создание динамического стека
- •Классы с деструкторами
- •Пример: динамически размещаемые строки
- •Ad hoc полиморфизм
- •Алгоритм выбора перегруженной функции
- •Перегрузка операторов
- •Перегрузка бинарных операторов
- •Перегрузка операторов присваивания и индексирования
- •Перегруженные операторы ввода-вывода « и »
- •Перегрузка оператора ( ) для индексирования
- •Операторы указателей
- •Указатель на член класса
- •Перегрузка new и delete
- •Наследование.
- •Методология объективно-ориентированного проектирования
- •Виртуальные функции
- •Абстрактные базовые классы
Изменчивость (mutable)
Ключевое слово mutable позволяет членам класса, переменные которого были объявлены как константы, быть, тем не менее, изменяемыми. Таким образом отпадает необходимость отказываться от постоянства, используя конструкцию const_cast<>. Это относительно новая возможность, поддерживаемая не всеми компиляторами С ++.
Создание и уничтожение объектов
Любому объекту требуется память и некоторое начальное значение. В C++ это обеспечивается с помощью объявлений, являющихся одновременно определениями. В большинстве случаев при обсуждении объявлений мы подразумеваем именно такие объявления. Например, в void foo ()
{ int n = 5 ; double z[10] = {0. 0}; struct gizmo { int i, j; } w= {3, 4}; …. }
все объекты создаются при входе в блок, когда вызывается foo().
Конструктор (constructor) — это функция-член, имя которой совпадает с именем класса. Он создает значения типа своего класса. Этот процесс включает в себя инициализацию членов данных и (зачастую) распределение свободной памяти с помощью new. Деструктор (destructor) — это функция-член, имя которой представляет собой имя класса, предваряемое символом - (тильда). Обычно деструктор предназначен для уничтожения значений типа класса, как правило, с помощью delete.
Из этих двух специальных функций-членов более сложны конструкторы. Они могут быть перегружены, могут принимать аргументы; ни то, ни другое невозможно для деструкторов1. Конструктор вызывается: когда связанный с ним тип используется в определении; когда для передачи значения функции применяется вызов по значению; или когда результат, возвращаемый функцией, предполагает создание значения соответствующего типа. Деструкторы вызываются неявно, когда объект выходит за пределы области видимости. Конструкторы и деструкторы не имеют возвращаемого типа и не могут использовать инструкцию return выражение.
Классы с конструкторами
Простейшее применение конструктора — использование его при инициализации.
Первый пример — реализация типа данных mod_int для хранения чисел, над которыми производятся вычисления по модулю.
//Числа для вычислений по модулю и инициализация конструктора
class mod_int { public: mod_int(int i); //объявление конcтруктора
void assign(int i) { v = i % modulus; } void print() const { cout <<v << '\t'; }
const static int modulus =60;
private: int v; };
//определение конструктора
mod_int::mod_int(int i) { v = i % modulus; }
const int mod_int::modulus;
Целая переменная v ограничена значениями 0,1,2,..modulus-1. Ответственность за выполнение этого ограничения лежит на программисте; все функции-члены должны вести себя, соблюдая это правило.
Функция-член mod_int:: mod_int (int) является конструктором. Она не имеет возвращаемого типа. Она вызывается, когда объявляются объекты типа mod_int. Это функция одного аргумента. При вызове конструктор ожидает выражение, преобразуемое по умолчанию к его целому параметру. Затем он создает и инициализирует объявленную переменную.
Вот некоторые примеры объявлений с использованием данного типа:
mod_int a(0); //a.v = 0 mod_int b(61); //a.v = 1
1К чести деструкторов надо сказать, что они (в отличие от конструкторов) могут быть виртуальными. — Примеч. перев.
но не так:
mod_int а; //недопустимо, т.к. нет списка параметров
Поскольку у этого класса лишь один конструктор со списком аргументов int, объявление mod_int должно получать целое выражение, передаваемое в качестве инициализующего значения. Заметьте, что не допуская объявления переменной типа mod_int без выражения-инициализатора, мы тем самый предотвращаем ошибки на этапе выполнения из-за неинициализованных переменных.
Конструктор по умолчанию
Конструктор, не требующий аргументов, называется конструктором по умолчанию. Это может быть конструктор с пустым списком аргументов, или конструктор, у которого все аргументы имеют значения по умолчанию. Конструктор по умолчанию имеет специальное назначение при инициализации массивов объектов своего класса.
Зачастую удобно перегружать конструктор с помощью нескольких объявлений функций. В нашем примере было бы желательно, чтобы v имела значение по умолчанию 0. Если мы добавим конструктор по умолчанию
mod_int () { v = 0; }
как функцию-член mod_int, то можно будет сделать следующие объявления:
mod_int; sl, s2; //оба инициализуют закрытый член v нулем mod_int d[5]; //массивы правильно инициализованы
В обоих объявлениях будет вызван конструктор с пустым списком параметров.
Если у класса нет конструктора, система предоставляет конструктор по умолчанию. Если конструктор у класса есть, но нет конструктора по умолчанию, размещение массива вызовет синтаксическую ошибку.
Обратите внимание, что в нашем примере с классом mod_int один и тот же конструктор может служить и для обычной инициализации, и в качестве конструктора по умолчанию:
inline: mod_int: :mod_int (int i = 0)
(v = i % modulus; }
Инициализатор конструктора
Существует специальный синтаксис для инициализации отдельных частей объекта с помощью конструктора. Инициализаторы конструктора (constructor initializer) для членов структуры и класса могут быть заданы через запятую в списке, который идет после двоеточия за списком параметров конструктора и предшествует телу. Давайте перепишем предыдущий пример:
//Конструктор по умолчанию для mod_int
mod_int: :mod_int(int i = 0) : v(i % modulus) {}
Обратите внимание, как инициализация заменила присваивание. Отдельные члены должны быть инициализованы как:
имя_члена (список выражений)
Не всегда членам можно присвоить значения в теле конструктора. Список инициализаторов необходим, когда нестатический член либо постоянен, либо является ссылкой.
