Вызов конструктора и деструктора

Как упоминалось ранее, конструктор и деструктор вызываются в программе автоматически при объявлении объектов класса. Не имеет значения, объявля­ется ли объект явно или создается динамически с помощью new.

Вызов того или иного конструктора зависит от формы описания объекта:

· Если после имени объекта или типа класса в операторе new ничего не указано или стоят пустые круглые скобки, вызовется конструктор по умолчанию.

· Если в скобках записаны параметры, вызывается конструктор с парамет­рами.

· Если в скобках находится имя объекта, то происходит вызов конструктора копирования.

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

Конструкторы вызываются в программе в порядке объявления объектов. Когда объявляется массив объектов, конструктор по умолчанию будет вы­зван столько раз, сколько элементов указано в объявлении массива.

При объявлении массива указателей на тип класса или единичного указателя никакие конструкторы не вызываются. Они будут вызваны позже при ини­циализации указателей оператором new.

Деструктор вызывается автоматически при разрушении объявленного по имени объекта, поэтому нет необходимости в явном вызове деструктора для разрушения локального объекта или для разрушения объектов перед выхо­дом из программы. Деструктор также вызывается автоматически, когда с по­мощью оператора delete освобождается указатель на объект класса. Без опе­ратора delete объект разрушен не будет. Разрешается и явный вызов деструктора для объекта, который выполняется, как и вызов любого другого метода класса.

Деструкторы вызываются в порядке, обратном порядку объявления имено­ванных объектов в программе. Вызов деструкторов объектов, объявленных через указатели, определяется следованием операторов delete для этих ука­зателей (листинг 14.8).

Иллюстрация вызовов конструкторов и деструктора

// главная функция

#include <iostream>

#include "Book.h"

using namespace std;

// конструктор по умолчанию

CBook::CBook(): m_year(0), m_pTitle("")

{

m_author[0] = '\0';

cout << "default CONSTRUCTORN\nthis = " << this;

}

// конструктор с параметрами

CBook:: CBook (char *author, char *title, int year): m_year (year), m_pTitle (title)

{

strncpy_s (m_author, 50, author, 49);

if (strlen (author) > 49)

m_author[49] = '\0';

cout << "with parameters CONSTRUCTORN\nthis = " << this;

}

// конструктор копирования

CBook:: CBook (CBook &o): m_year (o.m_year) {

strcpy_s (m_author, strlen (o.m_author)+1, o.m_author);

m_pTitle = new char [strlen (o.m_pTitle) + 1 ];

strcpy_s (m_pTitle, strlen (o.m_pTitle) + 1, o.m_pTitle);

cout << "CONSTRUCTOR of copying\nthis = " << this;

}

// деструктор

CBook:: ~CBook ()

{      delete [ ] m_pTltle;

cout << "DESTRUCTOR\t " << this << endl; }

 

void view (char*, CBook&);

int main ()

{

// объявление с вызовом конструктора по умолчанию

CBook book;

book.setAuthor ("Robert Lafore");

book.setTitle ("Object-Oriented Programming in С++");

book.setYear (2004);

view ("book", book);

// объявление с вызовом конструктора с параметрами

CBook obj ("Carrol L.", "Alice in Wonderland", 2002);

view ("obj", obj);

// объявление с вызовом конструктора копирования

CBook copy (obj);

view ("copy obj", copy);

// объявление через указатель с вызовом конструктора с параметрами СВоок *р;.

р = new CBook ("Herbert Schildt", "С++ The Complete Reference", 2003);

view ("pointer p", *p);

// разрушение объекта, объявленного через указатель

delete р;

//return 0;

}

// функция вывода состояния объекта класса СВоок

void view (char *s, CBook &o)

{

cout << "\nState of object V " << s << " \'\n";

cout << "Author:\t" << o.getAuthor () << endl;

cout << "Title:\t" << o.getTitle () << endl;

cout << "Year:\t" << o.getYear () << endl << endl;

}

 

В программе показаны результаты работы конструкторов и деструктора клас­са своок. В связи с тем, что эти методы вызываются автоматически, в реали­зацию каждого из них добавлен вывод сообщения с названием метода, а так­же вывод адреса начала объекта в оперативной памяти. В примере определена дополнительная функция view (), при помощи которой выво­дится состояние объекта, чей адрес получает функция.

В главной функции первым вызывается конструктор по умолчанию, когда объявляется объект book. Далее для объекта book при помощи методов класса setAuthor (), setTitie () и setYear () устанавливаются значения дан­ных m_author, m_pTitie и m_Year, после чего выводится состояние объекта. Вторым вызывается конструктор с параметрами, создающий объект obj с инициализацией данных этого объекта. Третий вызываемый конструктор, который порождает являющийся копией obj объект сору — это конструктор копирования. После вывода состояния сору при помощи оператора динами­ческого выделения памяти и конструктора с параметрами создается объект, адрес которого возвращает оператор new.

Оператор delete в конце программы освобождает указатель р и вызывает деструктор класса, который разрушает последний созданный объект. Далее деструктор автоматически вызывается три раза, разрушая объекты copy, obj и book.

 

Указатель this

Указатель, обозначаемый ключевым словом this, представляет собой неявно определенный указатель на сам объект и является скрытой внутренней пере­менной класса. Отсюда следует:

this — это адрес активного объекта в оперативной памяти.

*this — сам активный объект.

this -> имя члена-данного класса указывает на данное активного объекта. Как правило, this -> не пишется для активного объекта в методах класса, которые обрабатывают это данное активного объекта.

this -> имя метода (список фактических параметров) вызывает метод для активного объекта. Как правило, this -> не пишется при вызове метода активным объектом класса.

Получить значение указателя в методах класса можно с помощью ключе­вого слова this.

this — это локальная переменная, недоступная за пределами класса. Уз­нать значение указателя this какого-либо объекта класса в функциях про­граммы можно только с помощью открытого метода класса, который воз­вращает это значение, или же просто воспользоваться оператором взятия адреса &.

Абсолютно каждый объект имеет свой собственный указатель this. Этот ука­затель не нужно объявлять в классе, так как объявление имя_класса *const this скрыто в классе как объявление указателя на константу. Для любого принадлежащего классу метода this неявно объявлен точно так же. Изме­нить this невозможно.

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: