Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OTVETY_K_EKZAMENU_PO_OOP.doc
Скачиваний:
13
Добавлен:
01.07.2025
Размер:
239.62 Кб
Скачать

16. Конст-ры, деструкторы.

Функция, имеющую явное назначение — инициализация объектов назется конст-ром. Конст-р в отличие от метода не может возвращать значения. 0н имеет то же имя, что и класс, в котором он определен. Если класс имеет конст-р, то объект этого класса при его создании будет проинициализирован. Если конст-ру требуются арг-ты, они должны быть предоставлены. Часто удобно иметь несколько способов инициализации объекта. Этого можно добиться, введя несколько конст-ров, напр: Конст-ры подчиняются тем же правилам разрешения конфликта совмещеных имен, что и остальные функции. Пока конст-ры значительно различаются типами своих парамов, компилятор может выбрать нужный в каждом конкретном случае: Таким образом, инициализация посредством конст-ра явл более компактной и более надежной, чем без него. Производные классы нуждаются в собственых, конст-рах и деструкторах. При описании конст-ра производного класса необходимо сначала вызвать конст-р баз класса для того, чтобы он инициализировал ту часть объекта производного класса, кот унаследована из баз класса. Всегда соблюдается следующий порядок инициализации объекта: сначала исполняется конст-р баз класса и затем исполняется тело конст-ра, если оно есть. Если баз класс имеет конст-р по умолчанию, то в порожденом класе конст-р не обязателен. Для реализации конст-ра производного класса может использоваться следующая форма записи: ИмяКласа::ИмяКласа (парамы): ИмяБазКласа (арг-ты){тело кон-ра}; Конст-р необходим для создание таблицы вирт-ых методов (VMT), без которой невозможно вызывать вирт-ые функции. Конст-ры создают среду, в которой работают методы. Иногда создание такой среды подразумевает захват каких-то ресурсов, кот должны быть освобождены после их использования. В рез-те некот класам требуется функция, кот будет гарантировано вызвана при уничтожении объекта, аналогично конст-ру, кот гарантировано вызывается при создании объекта. Такая функция в C++ назется деструктором. Как правило, деструктор очищает память и освобождает ресурсы. 0н вызывается неявно, когда автоматическая переменая выходит из области видимости, удаляется объект из свободной памяти и т.п. В остальных ситуациях юзеру приходится уничтожать объект явным образом. Чаще всего деструктор используется для освобождения памяти, выделеной конст-ром. Уничтожение объектов производных класов: сначала уничтожается произ класс, затем баз класс, затем баз баз (если есть) и т.д. Рекомендуется все общие деструкторы объявлять как virtual, так как освобождать память необходимо для фактического класса объекта.

17. Конст-р копирования, Конст-р присваивания.

0бъект класса без конст-ров можно инициализировать путем присваивания ему другого объекта этого класса. Это можно делать и тогда, когда конст-ры описаны. По существу, имеется конст-р по умолчанию, определеный как почленая копия объекта того же класса. Если для класса X такой конст-р по умолчанию нежелателен, его можно переопределить конст-ром с именем Х(Х&). Семантика вызова по значению требует, чтобы локальная копия типа парама создавалась и инициализировалась от значения выражения, переданого как фактический парам. Для этого необходим конст-р копии. Компилятор предоставляет такой конст-р по умолчанию. Его сигнатура: ИмяКласа::ИмяКласа (const ИмяКласа &); Компилятор производит копирование путем почленой инициализации. Это не всегда применимо. В большинстве случаев, указатель явл адресом объекта, удаляемого при выходе из контекста. 0днако, код, в котором производится действие по дублированию значения указателя, а не объекта, на кот он указывает, может быть ошибочным. Дело в том, что удаление воздействует на др экземпляры, все еще предполагающие, что объект существует. Поэтому важно, чтобы класс имел свою собственую явно определеную копию конст-ра. Все хорошо разработаные классы должны иметь конст-р копирования, особено те, кот имеют дело с динамической памятью, открытыми файлами, любыми указателями.

Конст-р присваивания: Исп-ние указателей - членов класса может привести к утечке памяти при обычном присваивании. Поэтому при разработке класса хорошим стилем считается обязательное исп-ние перегруженого оператора присваивания. Для класса с именем х оператор вида х& operator= (const x &) назется конст-ром присваивания. Иногда такое действие назют глубоким копированием, в то время как не перегруженый оператор присваивания назется поверхностным копированием. Вышеприведеный способ перегрузки оператора присваивания для класса intarray не решает полностью все проблемы. Пример: intarray *а, *b; a=new intarray(2); b=new intsortedarray(2); a->setitem(0,3); b->setitem(0,l); intsortedarray *v=dynamic_cast<intsortedarray*>(b);

if (v) v->setsorted(true); *b=*a; В рез-те работы этого фрагмента у объекта *b даные - члены класса будут несогласованы - масив будет не упорядочен, в то время как функция issorted() вернет значение true. Для устранения этой проблемы необходимо добавить к конст-ру присваивания класса intarray модификатор virtual и у каждого производного класса необходимо его переопределять. Напр, для класса intsortedarray можно использовать реализацию оператора присваивания: intarray& intsortedarray::operator=(const intarray &a) {intarray::operator=(a);

const intsortedarray *w=dynamic_cast<const intsortedarray*>(&a); if (w) fsorted=w->fsorted;

else if (fsorted) sort(); return *this;};