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