Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
39
Добавлен:
16.04.2013
Размер:
99.33 Кб
Скачать

Создание и уничтожение объектов

Любому объекту требуется память и некоторое начальное значение. В 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 выражение.

6.1. Классы с конструкторами

Простейшее применение конструктора — использование его при инициализации.

Первый пример — реализация типа данных 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) {}

Обратите внимание, как инициализация заменила присваивание. Отдельные члены должны быть инициализованы как:

имя_члена (список выражений)

Не всегда членам можно присвоить значения в теле конструктора. Список инициализаторов необходим, когда нестатический член либо постоянен, либо является ссылкой.

Соседние файлы в папке Тельминов (мб)