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

15.8. Конструкторы и деструкторы (резюме)

При создании классов с новыми типами данных системы программирования на базе языка C++ облегчают работу программиста тем, что автоматически создают средства для объявления объектов нового типа, их инициализации и уничтожения. Эти средства получили название конструкторов (созидателей) и деструкторов (разрушителей).

Создание объекта в соответствии с описанием данных в классе сводится к выделению ресурсов (как правило, речь идет об участке оперативной памяти) для хранения объекта и инициализации полей данных. К числу наиболее характерных методов инициализации участков памяти, которые не зависят от специфики задач, относятся три следующие процедуры:

    • очистка выделенной памяти (для числовых данных это соответствует записи нулей, для строковых данных – записи пустых строк);

    • заполнение выделенных полей константами, указанными при объявлении объекта;

    • копирование в поля нового объекта содержимого полей ранее объявленного объекта.

В случае необходимости программист может включить в свой класс указанные конструкторы:

#include <iostream.h>

class B {

int x;

public:

B(){x=0; cout<<"Def_Constr_B "<<this<<endl;}

B(int y){x=y; cout<<"Init_Constr_B "<<this<<endl;}

B(const B &z){x=z.x; cout<<"Copy_Constr_B "<<this<<endl;}

int get_x(){return x;}

~B(){cout<<"Destr B"<<this<<endl;}

};

void main()

{ B q1; //обращение к конструктору по умолчанию

B q2(2); //обращение к конструктору инициализации

B q3(q2); //прямое обращение к конструктору копирования

B q4=q1; //косвенное обращение к конструктору копирования

cout<<"q1="<<q1.get_x()<<endl;

cout<<"q2="<<q2.get_x()<<endl;

cout<<"q3="<<q3.get_x()<<endl;

cout<<"q4="<<q4.get_x()<<endl;

}

//=== Результат работы ===

Def_Constr_B 0012FF88 //конструктор по умолчанию, адрес q1.x

Init_Constr_B 0012FF84 //конструктор инициализации, адрес q2.x

Copy_Constr_B 0012FF80 //конструктор копирования, адрес q3.x

Copy_Constr_B 0012FF7C //конструктор копирования, адрес q4.x

q1=0

q2=2

q3=2

q4=0

//Деструктор вызывается автоматически при выходе из блока

Destr B 0012FF7C //уничтожение объекта q4

Destr B 0012FF80 //уничтожение объекта q3

Destr B 0012FF84 //уничтожение объекта q2

Destr B 0012FF88 //уничтожение объекта q1

Если программист не включает в свой класс ни одного конструктора, то компилятор автоматически вписывает ему конструктор по умолчанию (в отличие от приведенного выше системный конструктор не чистит память) и конструктор копирования.

Специфика конструкторов заключается в следующем:

    • имя конструктора совпадает с именем класса;

    • перед именем конструктора отсутствует указание о типе возвращаемого значения;

    • как и любая другая функция, конструктор может иметь список параметров, передаваемых ему при объявлении объекта. В заголовке конструктора могут присутствовать параметры по умолчанию. У стандартного конструктора по умолчанию список параметров пуст;

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

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

Пример нестандартного конструктора по умолчанию, который пришлось написать нам самим, мы видели в классе Rational – с нулевым знаменателем работать было бы нельзя.

В отличие от конструкторов, создающих объекты, деструктор их уничтожает, освобождая ресурсы, выделенные для хранения объекта. Деструктор у класса может быть только один. Если программист не напишет свой деструктор, который производит дополнительные нестандартные действия, то компилятор подключит системный деструктор. Имя деструктора начинается с "тильды", которая предшествует имени класса. Параметров у деструктора нет:

Rational v1; //объявление с помощью конструктора по умолчанию

Rational v2(1,2); //использование конструктора инициализации

Rational v3(v2); //использование конструктора копирования

~Rational(); //деструктор

Явно к деструктору обращаться не приходится, т.к. он вызывается автоматически при выходе из блока программы, в котором был создан объект.

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

class array {

int size;

char *p;

public:

array(int dim); //конструктор создания динамического массива

~array(){ delete [] p; } //деструктор разрушения массива

.........................

};

array::array(int dim) //тело конструктора

{ p=new char[dim]; //запрос памяти под динамический массив

if(!p) //если память не выделена

{ cout<<"Allocation error"; exit(1); }

size=dim;

}