Программирование на C и C++

Онлайн справочник программиста на C и C++

Конструкторы и деструкторы

Перед использованием объекта может потребоваться инициализировать некоторые его данные. Для примера рассмотрим класс queue, определенный выше в этой главе. Перед тем как использо­вать queue, необходимо присвоить переменным rloc и sloc значения 0, используя функцию init(). Поскольку требование инициализации является чрезвычайно распространенным, то С++ позво­ляет производить инициализацию объектов во время их создания. Такая автоматическая иници­ализация выполняется с помощью функции, которая называется конструктором.

Функция-конструктор, являющаяся членом класса и имеющая имя, совпадающее с именем класса, представляет собой специальный тип функции. В качестве примера ниже показано, как выглядит класс queue, преобразованный таким образом, чтобы использовать для инициализации конструктор:

/ / создание класса очередь
class queue {
int q[100];
int sloc, rloc;
public:
queue (); // конструктор
void qput(int i);
int qget ();
};

Обратим внимание, что конструктор queue() не имеет типа возвращаемого значения. В С++ функции-конструкторы не могут возвращать значений.

Код, реализующий функцию queue(), выглядит следующим образом:

// конструктор
queue ::queue ()
{
sloc = rloc = 0;
cout << "Queue initialized. \n";
}

Обратим внимание, что выводимое сообщение «queue initialized» служит для иллюстрации рабо­ты конструктора. В обычной практике большинство конструкторов не занимаются выводом или вводом данных. Они служат для инициализации.

Конструктор объекта вызывается автоматически при создании объекта. Это означает, что он вызывается тогда, когда происходит объявление объекта. В этом заключается важнейшее разли­чие между объявлениями в языке С и в С++. В С объявления переменных, попросту говоря, являются пассивными и в большинстве случаев выполняются во время компиляции. Иными слова­ми, в языке С объявления переменных не являются исполнимыми инструкциями. В отличие от этого в С++ объявления переменных служат активными инструкциями, исполняемыми по суще­ству во время работы программы. Одна из причин этого заключается в том, что объявление объекта может требовать вызова конструктора, то есть вызывать выполнение функции. Хотя это различие может показаться едва уловимым и носить больше академический характер, как будет видно да­лее, оно может оказывать существенное влияние на инициализацию переменных.

При инициализации глобальных или статических объектов конструктор вызывается только один раз. Для локальных объектов конструктор вызывается всякий раз, когда встречается объявление объекта.

Дополнением конструктора является деструктор. Во многих случаях перед уничтожением объекта необходимо выполнить определенные действия. Локальные объекты создаются при входе в соот­ветствующий блок программы и разрушаются при выходе из него. Глобальные объекты уничто­жаются при завершении работы программы. Имеется много причин тому, чтобы существовал деструктор. Например, может потребоваться освободить память, которая была ранее зарезерви­рована. В С++ за дезактивацию отвечает деструктор. Он имеет то же самое имя, что и конструк­тор, только к нему добавлен значок ~. Ниже представлен вариант класса queue, использующий конструктор и деструктор. (Следует иметь в виду, что класс queue не нуждается в деструкторе, поэтому ниже он приведен только для иллюстрации.)

// создание класса очередь
class queue {
int q[100];
int sloc, rloc;
public:
queue(); // конструктор
~queue(); // деструктор
void gput(int i);
int qget();
};
// конструктор
queue::queue()
{
sloc = rloc = 0;
cout << "Queue initialized.\n";
}
// деструктор
queue ::~queue ()
{
cout << "Queue destroyed.\n";
}
Для того чтобы продемонстрировать работу конструктора и деструктора, ниже представлена но­вая версия программы:
#include <iostream.h>
// создание класса очередь
class queue {
int q[100];
int sloc, rloc;
public :
queue (); // конструктор
~queue(); // деструктор
void gput(int i);
int qget();
};
/ / конструктор
queue::queue ()
{
sloc = rloc = 0;
cout << "Queue initialized.\n";
}
// деструктор
queue::~queue ()
{
cout << "Queue destroyed.\n";
}
void queue::qput(int i)
{
if (sloc == 99) {
cout << "Queue is full.\n";
return;
}
sloc++;
q[sloc] = i;
}
int queue::qget()
{
if (rloc == sloc) {
cout << "Queue underflow.\n";
return 0;
}
rloc++;
return q[rloc];
}
int main()
{
queue a, b; // создание двух объектов типа queue
a.qput(10);
b.qput(19) ;
a.qput(20);
b.qput(1);
cout << a.qget ()<< " ";
cout << a.qget ()<< " ";
cout << b.qget()<<" ";
cout << b.qget()<< "\n";
return 0;
}

Эта программа выводит на экран следующий текст:

Queue initialized.
Queue initialized.
10 20 19 1
Queue destroyed.
Queue destroyed.