Объектно-ориентированное программирование — Деструктор
- Объектно-ориентированное программирование
- Локальные и глобальные переменные
- Подпрограммы и их аргументы
- Определение данных
- Операторы динамического распределения памяти
- Перегрузка функций и операций
- Правила составления перегружаемых функций и операций
- Класс как обобщение структуры
- Определение первичного класса
- Перегрузка операций
- Конструкторы
- Список инициализации
- Деструктор
- Дружественные классы
- Статические элементы класса
- Шаблоны функций
Деструктором называется составная функция класса, которая вызывается перед разрушением объекта. Это означает, что деструктор вызывается в следующих случаях:
· при выходе из области видимости;
· при выполнении операции delete для объектов, размещенных в динамической памяти;
· непосредственно, как составная функция.
Уже обсуждалось, что класс может иметь несколько конструкторов, все эти конструкторы имеют одинаковое имя, совпадающее с именем класса. Приведём правила определения деструкторов:
· класс имеет ровно один деструктор;
· имя деструктора совпадает с именем класса с добавленным впереди символом тильды «~»;
· деструктор не имеет аргументов и не имеет возвращаемого значения.
Если же деструктор не определить явно, то он будет определен по умолчанию, как составная функция
~ имя_класса() {};
и будет находиться в открытой части класса.
Пример. Определим класс, объектом которого является стек, состоящий из элементов, размещающихся в массиве целых чисел. Поскольку конструктор будет захватывать динамическую память, то необходим деструктор, который эту память будет освобождать после окончания работы со стеком.
#include
#include
// Класс — целочисленный стек
class IntStack
{
// Закрытые элементы
int *v; // Массив под стек
int size, top; // Размер стека и положение вершины
public: // Общедоступные элементы
IntStack(int n = 10): size(n), top(n) // Конструктор
{
v = new int[n]; // Выделение памяти под массив (стек)
}
~IntStack() // Деструктор
{
delete []v; // Освобождение памяти
}
int& operator++(int); // Перегрузка постфиксной операции ++
int operator--(); // Перегрузка префиксной операции --
};
int& IntStack::operator++(int) // Перегрузка постфиксной операции ++
{
return v[--top];
}
int IntStack::operator--() // Перегрузка префиксной операции --
{
return v[top++];
}
int main()
{
clrscr(); // Очистка экрана
IntStack *ps = new IntStack(20); // Создание стека ps
// в динамической памяти
IntStack s; // Создание стека s (по умолчанию 10 элементов)
for(int i = 0; i < 10; i++)
s++ = i; // запись чисел 0,1,2,... в стек
cout<<"Содержимое стека:\n";
for(int j = 0; j < 10; j++)
cout << --s << '\n'; // Чтение из стека
(*ps)++ = 100; // Пример занесения в стек ps числа 100
s.~IntStack(); // Явное разрушение стека s
delete ps; // Разрушение стека ps
getch(); // Ожидание нажатия клавиши
return 0; // Выход из программы
}
В результате работы этой программы на экран будут выведены числа 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 , каждое с новой строки.
Пример. Определим класс трассировочного типа, позволяющий отслеживать вход в блок и выход из блока программы, для которого определен объект этого класса. Воспользуемся с этой целью свойством запуска конструктора при вхождении в блок, содержащий объект, инициализируемый этим конструктором. При выходе из блока будет вызываться деструктор.
#include
#include
#include
// Трассировочный класс
class trace
{
const char* msg;
public:
trace(char *m): msg(m) // Конструктор
{
// Вывод сообщения о входе в блок
fprintf(stderr, "Входим в %s\n", msg);
}
~trace() // Деструктор
{
// Вывод сообщения о выходе из блока
fprintf(stderr, "Выходим из %s\n", msg);
}
};
void subr()
{
trace t("subr");
}
int main()
{
clrscr(); // Очистка экрана
trace t("main");
cout<<'\n'; // Перевод строки
subr();
cout<<'\n'; // Перевод строки
for(int i = 0; i < 5; i++)
{
trace t("internal");
}
cout<<'\n'; // Перевод строки
return 0; // Выход из программы
}
Результаты работы программы
Входим в main
Входим в subr
Выходим из subr
Входим в internal
Выходим из internal
Входим в internal
Выходим из internal
Входим в internal
Выходим из internal
Входим в internal
Выходим из internal
Входим в internal
Выходим из internal
Выходим из main