- •Чистые виртуальные функции и абстрактные классы
- •Производные классы с конструкторами и деструкторами
- •Виртуальные деструкторы
- •Обобщенный пример наследования
- •Модульность классов
- •Расширяющяся иерархия классов
- •Узловые классы
- •Множественное наследование классов
- •Шаблоны
- •Шаблоны функций
- •Перегрузка шаблонов функций
- •Шаблоны классов
- •Друзья Дружественные функции
- •Дружественные классы
- •Статические элементы класса
Виртуальные деструкторы
Методы и деструкторы (но не конструкторы !) могут быть виртуальными. Виртуальные деструкторы обычно применяются, когда в некотором классе необходимо удалить объекты производного класса, на которые ссылаются указатели на базовый класс. Типичной является ситуация, когда динамически создается объект производного класса, а используется указатель на базовый класс.
Пример 38.
Рассмотрим простое наследование по схеме Base <- Derive1 <- Derive2. Программа (на основе примера 36) иллюстрирует порядок работы конструкторов и деструкторов в классах при динамическом выделении памяти объекту производного класса через указатель на базовый класс и уничтожение объектов с использованием виртуального деструктора. Если объявить деструктор базового класса виртуальным, то все деструкторы производных классов также являются виртуальными.
#include<iostream.h>
#include<conio.h>
class Base
{ public:
Base () { cout << "Конструктор базового класса Base\n"; }
virtual ~Base () { cout << "Деструктор базового класса Base\n"; }
};
class Derive1: public Base
{ public:
Derive1 () { cout << "Конструктор производного класса Derive1\n"; }
~Derive1 () { cout << "Деструктор производного класса Derive1\n"; }
};
class Derive2: public Derive1
{ public:
Derive2 () { cout << "Конструктор производного класса Derive2\n"; }
~Derive2 () { cout << "Деструктор производного класса Derive2\n"; }
};
void main ()
{ clrscr ();
Base *pb = new Derive2; // выделение памяти объекту Derive2
if (! pb)
{ cout << "Недостаточно памяти\n";
return 1; // аварийное окончание программы
}
cout << endl;
delete pb; // вызов всех деструкторов производных и базового классов
return 0;
}
Результаты программы:
Конструктор базового класса Base
Конструктор производного класса Derive1
Конструктор производного класса Derive2 // создание объекта типа Derive2
Деструктор производного класса Derive2
Деструктор производного класса Derive1
Деструктор базового класса Base // уничтожение объекта типа Derive2
Комментарии к программе:
При разрушении объекта с помощью операции delete через указатель на базовый класс были корректно вызваны деструкторы всех классов в нужном порядке. Если бы деструктор базового класса не был объявлен виртуальным, то вызывался бы только деструктор базового класса (проверьте это). Динамическая память, выделенная объекту конструктором, при разрушении объекта обычным деструктором не освобождалась бы корректно.
Пример 39.
Рассмотрим модифицированную программу на основе примеров 33 и 35, в которой используется абстрактный базовый класс Figure с чистой виртуальной функцией show_area() и виртуальным деструктором. Базовый класс Figure описывает плоскую фигуру с двумя измерениями, которые задаются конструктором со вторым параметром по умолчанию. Нельзя создать объект данного класса, но можно определить указатель на тип класса. От этого класса на основе расширяющегося наследованиия строятся производные классы по схеме: Figure <- (Triangle, Rectangle, Circle). В производных классах определены свои функции show_area().
С помощью указателя на базовый класс можно сослаться на объекты производных классов и вывести данные о них на экран в процессе исполнения программы. Виртуальный деструктор последовательно уничтожает объекты в порядке обратном тому, в котором они создавались конструктором.
#include<iostream.h>
#include<conio.h>
class Figure // абстрактный базовый класс
{ protected: // защищенные элементы, доступные в производных классах
double x, y;
public:
Figure (double i, double j=0) // конструктор с параметром по умолчанию
{ x = i, y = j; // задание измерений фигур
cout<<"Конструктор базового класса Figure\n";
}
virtual void show_area() = 0; // чистая виртуальная функция
virtual ~Figure () // виртуальный деструктор Figure { cout<<"Деструктор базового класса Figure\n";}
};
class Triangle: public Figure // производный класс Triangle
{ public:
Triangle (double i, double j): Figure ( i, j) // конструктор Triangle
{ cout<<"Конструктор Triangle\n"; }
void show_area() // виртуальная функция Triangle
{ cout<<"Треугольник с высотой "<< x <<" и основанием "<< y;
cout<<" имеет площадь = "<< x*0.5*y <<endl;
}
~Triangle() // виртуальный деструктор Triangle
{ cout<<"Деструктор классаTriangle \n";}
};
class Rectangle: public Figure // производный класс Rectangle
{ public:
Rectangle (double i, double j): Figure ( i, j) // конструктор Rectangle
{ cout<<"Конструктор Rectangle\n"; }
void show_area() // виртуальная функция Rectangle
{ cout<<"Прямогольник со сторонами "<< x <<" и "<< y;
cout<<" имеет площадь = "<< x*y <<endl;
}
~Rectangle() // виртуальный деструктор Rectangle { cout<<"Деструктор класса Rectangle\n"; }
};
class Circle: public Figure // производный класс Circle
{ public:
Circle (double i): Figure ( i) // конструктор Circle {cout<<"Конструктор Circle\n"; }
void show_area() // виртуальная функция Circle
{ cout<<"Круг с радиусом "<< x;
cout << " имеет площадь = " << 3.14*x*x << endl;
}
~Circle() // виртуальный деструктор Circle { cout<<"Деструктор класса Circle\n"; }
};
void main ()
{ clrscr();
cout << "Работа программы:\n";
Figure *p; // объявление указателя класса Figure
Triangle t (3,4); // создание объекта класса Triangle
Rectangle r (5,6); // создание объекта класса Rectangle
Circle c (2); // создание объекта класса Circle
p = &t; // базовый указатель на объект типа Triangle
p -> show_area(); // вывод сообщения о площади объекта типа Triangle
p = &r; // базовый указатель на объект типа Rectangle
p -> show_area(); // вывод сообщения о площади объекта типа Rectangle
p = &c; // базовый указатель на объект типа Circle
p -> show_area(); // вывод сообщения о площади объекта типа Circle
}
Результаты программы:
Работа программы:
Конструктор базового класса Figure
Конструктор Triangle
Конструктор базового класса Figure
Конструктор Rectangle
Конструктор базового класса Figure
Конструктор Circle
Треугольник с высотой 3 и основанием 4 имеет площадь = 6
Прямогольник со сторонами 5 и 6 имеет площадь = 30
Круг с радиусом 2 имеет площадь = 12.56
Деструктор класса Circle
Деструктор базового класса Figure
Деструктор класса Rectangle
Деструктор базового класса Figure
Деструктор классаTriangle
Деструктор базового класса Figure
