
- •Структуры
- •Массив структур
- •Указатели на структуру
- •Битовые поля
- •Объединения
- •Перечисления
- •Переименование типов
- •Открытие файла
- •Функции работы с файлами
- •Форматный ввод/вывод
- •Ввод/вывод строк. Функции позиционирования
- •Чтение из двоичного файла и запись в него
- •Свойства ООП
- •1.1 Свойства ООП
- •Понятие класса в С++
- •1.2 Понятие класса С++
- •Создание класса
- •1.3 Создание класса
- •Члены класса
- •1.4 Члены класса
- •Инкапсуляция
- •1.5. Инкапсуляция
- •1.6 Функции-члены класса
- •Реализация понятия «дата» при помощи структуры
- •1.7 Реализация понятия «дата» при помощи структуры
- •Реализация понятия «дата» при помощи класса
- •1.8 Реализация понятия «дата» при помощи класса
- •Определение и вызов функций–членов класса
- •Выводы. Примеры
- •1.9 Выводы
- •1.10 Пример создания класса
- •Конструкторы
- •2.1 Конструкторы
- •2.2 Пример класса без конструктора
- •2.3 Пример класса с конструктором
- •2.4. Конструктор с параметрами по умолчанию
- •2.5. Деструкторы
- •2.6. Пример класса с конструктором и деструктором
- •2.7. Подставляемые или inline функции.
- •2.8. Подставляемые функции-члены.
- •2.9. Указатель this
- •2.10. Использование указателя this
- •Дружественные функции
- •3.1 Дружественные функции
- •3.2 Пример дружественной функции
- •3.3 Дружественные классы
- •3.4. Уточнение имени элемента.
- •3.5. Определение переменных непосредственно перед использованием
- •3.6. Статические элементы класса.
- •2.7. Пример
- •Перегруженные функции
- •4. Перегрузка функций и операций
- •4.1 Полиморфизм
- •4.2 Перегруженные функции
- •4.3 Перегрузка конструктора
- •4.4 Выбор экземпляра функции
- •4.5 Перегрузка стандартных операций
- •4.6 Перегрузка операций сложения и присваивания
- •4.7 Перегрузка операций ++ и --
- •4.8 Дружественные функции-операции
- •4.9 Перегрузка операции индексации []
- •4.10 Аргументы по умолчанию
- •5. Работа с объектами
- •5.1 Ссылки в С++
- •5.2 Передача объектов, как аргументов функции
- •5.3 Массивы объектов
- •5.4 Указатель на объект
- •5.5 Динамическое выделение памяти. Операторы new, delete.
- •5.6 Локальные классы
- •5.7 Вложенные классы
- •5.8 Имена заголовочных файлов в С++
- •5.9 Строковые переменные в С++.
- •6. Наследование
- •6.1 Понятие наследования
- •6.2 Базовые и производные классы
- •6.3 Одиночное и множественное наследование
- •6.4 Управление доступом производных классов
- •6.5 Пример
- •6.6 Конструкторы с параметрами при наследовании
- •6.7 Конструкторы при множественном наследовании
- •7. Виртуальные функции. абстрактные классы
- •7.1 Указатели на производные типы
- •7.2 Виртуальные функции
- •7.3 Пример
- •7.4 Чистые виртуальные функции и абстрактные типы
- •7.5 Виртуальные базовые классы
- •7.6 Шаблоны
- •7.7 Шаблоны функций
- •7.8 Пример
- •7.9 Использование шаблонов с двумя типами параметров
- •7.10 Шаблоны классов
7. Виртуальные функции. абстрактные классы
7.1 Указатели на производные типы
Указатели на производные типы — это одна из форм реализации динамического полиморфизма в С++. Указатель на базовый тип и производный тип зависимы.
Например: B_class -> D_class
В С++ всякий указатель на базовый класс В может быть также указателем на производный класс D.
B_class *p;
B_class b_ob;
D_class D_ob;
p=&B_ob;
p=&D_ob;
((D_class*)p)->f(); |
— приведение типа |
При создании указателя на объект базового класса происходит присвоение как адрес объекта базового класса, так и производную класса.
Все элементы класса D, наследуемые от класса B, могут быть доступны через использование указателя p.
Если требуется иметь доступ к элементам, используется указатель на базовый класс, который надо привести к указателю на произвольный тип.
p — указатель на базовый класс
f — функция-член класса D.
Обратное неверно – нельзя использовать указатель на производный класс для присвоения ему адреса объекта базового класса.
При использовании операций инкремент, декремент указатель изменяется относительно базового типа.
Когда указатель на базовый класс указывает на производный, инкремент не делает его указывающим на следующий элемент производного класса.
7.2 Виртуальные функции
Виртуальные функции представляют собой функции-члены класса, которые переопределяются в производном классе. Механизм виртуальных функций обеспечивает динамический полиморфизм.
Виртуальные функции – это функции, которые объявляются с использованием ключевого слова virtual в базовом классе и переопределяются в одном или нескольких производных классов. Прототипы функций должны быть одинаковы, иначе механизм переопределения не включается. Виртуальную функцию вызывают через указатель базового класса, используемого в качестве ссылки на объект производного класса.
Если имеется несколько производных классов от содержащего виртуальную функцию базового класса, то при ссылке указателя базового класса на разные объекты производных классов будут выполнены различные версии виртуальных функций.
В одном или нескольких производных классах перераспределение виртуальной функции может отсутствовать, при этом механизм виртуальной функции сохраняется, и вызывается функция базового класса, ближайшего к тому, где функция не переопределена, т.е. соблюдается иерархия наследственной характеристики.
Спецификатор virtual предполагает принадлежность функции классу, поэтому виртуальная функция не может быть ни глобальной функцией, ни статическим членом класса, поскольку вызов виртуальной функции нуждается в конкретном объекте для выяснения того, какую именно функцию следует вызывать.
Подменяющая функция в производном классе также считается виртуальной, даже при отсутствии спецификатора virtual.
Виртуальная функция должна быть членом класса, она не может быть дружественной для класса, в котором определена, но может быть другом другого класса. Удобство виртуальной функции состоит в том, что базовый класс создаёт основной интерфейс, который будет иметь производный класс, производный класс задаёт свой метод.
7.3 Пример
# include<iostream>
using namespace std;
class figure{
protected: double x,y;
public:void set_dim(double i, double j=0){
x=i;
y=j;}
virtual void show_area(){
cout<<”площадь не определена\n”;}};
class triangle:public figure{
public:void show_area(){
cout<<”треугольник с высотой”<<x<<”и основанием”<<y;
cout<<”имеет площадь”<<x*0,5+y;}};
class rectangle:public figure{
public:void show_area(){
cout<<”прямоугольник со сторонами”<<x<<y;
cout<<”имеет площадь”<<x*y;}};
class circle:public figure{
public:void show_area(){
cout<<”круг с радиусом”<<x;
cout<<”имеет площадь”<<3.14*x*x;}};
main()
{figure f,*p;
triangle t;
rectangle s;
circle c;
p=&f;
p->set_dim(1,2); p->show_area();
p=&t;
p->set_dim(3,4); p->show_area();
p=&s;
p->set_dim(5,6); p->show_area();
p=&c;
p->set_dim(8); p->show_area();
}
Программа позволяет определить площади некоторых плоских фигур с использованием виртуальной функции. Виртуальная функция — определение площади.
7.4 Чистые виртуальные функции и абстрактные типы
Чистые виртуальные функции используются в случае, когда в виртуальной функции базового класса отсутствует значимое действие, при этом в каждом производном классе такая функция должна быть определена. Чистые виртуальные функции в базовом классе не определяются; вместо этого помещаются их прототипы.
virtual тип <имя_функции> (список параметров)=0;
Присваивание к нулю в этом случае означает отсутствие тела функции. При таком объявлении виртуальные функции в каждом производном классе должно выполняться переопределение функции, или компилятор выдаст сообщение об ошибке. Можно объявить функцию как чистую виртуальную.
Если класс имеет хотя бы одну чистую виртуальную функцию – это класс абстрактный. Нельзя создать объект этого класса, он используется исключительно как базовый, можно создавать указатель на объект базового класса и применять для реализации механизма виртуальных функций.
Пример:
#include <iostream>
using namespace std;
class figure{
protected: double x,y;
public:void set_dim(double i, double j=0)
x=i;
y=j;}
virtual void show_area()=0;};
class triangle:public figure{
public:void show_area(){
cout<<”треугольник с высотой”<<x<<”и основанием”<<y;
cout<<”имеет площадь”<<x*0,5+y;}};
class rectangle:public figure{
public:void show_area(){
cout<<”прямоугольник со сторонами”<<x<<y;
cout<<”имеет площадь”<<x*y;}};
class circle:public figure{
public:void show_area(){
cout<<”круг с радиусом”<<x;
cout<<”имеет площадь”<<3.14*x*x;}};
main()
{figure f,*p;