
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Виртуальные деструкторы
Виртуальные деструкторы необходимы при использовании указателей на базовый класс при выделении памяти под динамически создаваемые объекты производных классов. Это обусловлено тем, что если объект уничтожается явно, например, используя операцию delete, то вызывается деструктор только класса, совпадающего с типом указателя на уничтожаемый объект. При этом не учитывается тип объекта, на который указывает данный указатель.
В случае объявления деструктора базового класса виртуальным, все деструкторы производных классов становятся так же виртуальными. При этом если будет выполняться явное уничтожение объекта производного класса для указателя на базовый класс, то в начале вызывается деструктор производного класса, а затем вверх по иерархии до деструктора базового класса.
Рассмотрим отличия в работе программы при использовании виртуальных деструкторов и в случае их отсутствия на примере программы вычисляющей площади некоторых фигур (круг, прямоугольник).
#include "iostream.h"
#include "iomanip.h"
#include "string.h"
class Shape // базовый класс
{protected:
float s; // площадь фигуры
public:
Shape(char *fig) : s(0)
{ cout << "конструктор класса Shape (фигура "<< fig <<')'<< endl;}
virtual ~Shape()
{ cout << "деструктор класса Shape" << endl;}
void virtual print()
{cout<<s<<endl;}
void virtual area()=0;
};
class Circle : public Shape // производный класс Круг
{ int r;
public:
Circle(char *name,int r): Shape(name)
{ cout << "конструктор класса Circle "<<endl;
this->r=r;
}
~Circle()
{ cout << "деструктор класса Circle " << endl;}
void area();
};
class Bar : public Shape // производный класс Прямоугольник
{ int n,m;
public:
Bar(char *name,int n,int m): Shape(name)
{ cout << "конструктор класса Bar "<<endl;
this->n=n;
this->m=m;
}
~Bar()
{ cout << "деструктор класса Bar " << endl;}
void area();
};
void Circle::area()
{ s=r*r*3.14;
cout<<"Площадь круга = ";
this->print();
}
void Bar::area()
{ s=n*m;
cout<<"Площадь прямоугольника = ";
this->print();
}
int main()
{ Shape *fg1,*fg2;
fg1=new Circle("Круг",2);
fg2=new Bar("Прямоугольник",3,4);
fg1->area();
fg2->area();
delete fg1;
delete fg2;
return 1;
}
Результат работы программы:
конструктор класса Shape (фигура Circle)
конструктор класса Circle
конструктор класса Shape (фигура Bar)
конструктор класса Bar
площадь круга =12.56
площадь прямоугольника =12
деструктор класса Circle
деструктор класса Shape
деструктор класса Bar
деструктор класса Shape
В случае если деструктор базового класса являлся бы не виртуальным, то при удалении объектов производных классов осуществлялся бы вызов только деструктора базового класса (т.е. класса для которого объявлен соответствующий указатель).
Если в классе имеются виртуальные функции, то желательно объявлять деструктор этого класса также виртуальным, даже если этого не требуется. Это может предотвратить возможные ошибки.