- •Операторы динамического распределения памяти
- •Перегрузка функций и операций
- •Объекты и классы Класс как обобщение структуры
- •Определение первичного класса
- •Перегрузка операций
- •Конструкторы
- •Список инициализации
- •Деструктор
- •Статические элементы класса
- •Дружественные классы
- •Шаблоны функций
- •Контейнерные классы Шаблоны классов
- •Параметризованные очереди и стеки
- •Бинарные деревья
- •Определение класса множества
- •Производные классы Доступ к полям и функциям базового класса
- •Класс дерева поиска
- •Параметризованный связный список
- •Множественное наследование
- •Виртуальные классы
- •Виртуальные функции Переопределение составной функции
- •Организация списка объектов различного типа
- •Виртуальные деструкторы
- •Абстрактные классы
Деструктор
Пример. Определим класс, объектом которого является стек, состоящий из элементов, размещающихся в массиве целых чисел. Поскольку конструктор будет захватывать динамическую память, то необходим деструктор, который эту память будет освобождать после окончания работы со стеком.
#include <iostream.h>
#include <conio.h>
// Класс - целочисленный стек
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 <stdio.h>
#include <conio.h>
#include <iostream.h>
// Трассировочный класс
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
