- •1. Объектно-ориентированный подход в программировании.
- •1.1 Инкапсуляция
- •1.2 Наследование
- •1.3 Полиморфизм
- •2.1 Перегружаемые (overload) функции
- •2.2 Перегружаемые (overload) операторы
- •2.3 Объектные типы данных: структуры, объединения, классы (обзор)
- •2.4. Конструкторы и деструкторы
- •2.8 Встраиваемые функции
- •2.7 Производные классы
- •2.9 Присваивание объектов
- •2.10 Передача в функции и возвращение объекта
- •2.11 Конструктор копирования
- •2.12 Указатели и ссылки на объекты
- •3.1. Модификаторы наследования
- •3.2 Конструкторы при наследовании
- •3.3 Деструкторы при наследовании
- •3.4 Совместимость типов
- •4. Виртуальные функции.
- •4.1. Раннее и позднее связывание
- •4.2 Полиморфизм и виртуальные методы
- •4.3. Использование указателей на базовые классы при адресации объектов произвольных классов.
- •4.4 Абстрактный класс
- •5. Дружественные функции.
- •5.1 “Дружественные” (friend) функции
- •6. Шаблоны функций и классов
- •6.1 Шаблоны функций
- •6.2 Шаблоны классов
4.3. Использование указателей на базовые классы при адресации объектов произвольных классов.
Если некоторый класс содержит виртуальную функцию, а производный от него класс содержит функцию с тем же именем и типами формальных параметров, то обращение к этой функции для объекта производного класса вызывает функцию, определённую именно в производном классе. Функция, определённая в производном классе, вызывается даже при доступе через указатель или ссылку на базовый класс. В таком случае говорят, что функция производного класса подменяет функцию базового класса. Если типы функций различны, то функции считаются разными, и механизм виртуальности не включается. Ошибкой является различие между функциями только в типе возвращаемого значения.
class Base
{ public:
virtual void f1();
virtual void f2();
virtual void f3();
void f();
};
class Derived : public Base
{ public:
void f1();
void f2(int); // Скрывает Base::f2()
char f3(); // Ошибка – различие только в типе возвращаемого значения!
void f();
};
Derived *dp = new Derived;
Base *bp = dp; // Преобразование указателя на производный класс в указатель на базовый класс
bp->f(); // Вызов Base::f
dp->f(); // Вызов Derived::f
dp->Base::f(); // Вызов Base::f
dp->f1(); // Вызов Derived::f1
bp->f1(); // Всё равно вызов Derived::f1!!!
bp->Base::f1(); // Вызов Base::f1 (использование явного квалификатора блокирует механизм виртуальности)
bp->f2(); // Вызов Base::f2
dp->f2(0); // Вызов Derived::f2
dp->f2(); // Ошибка, т.к. не задан параметр
dp->Base::f2(); // Вызов Base::f2
Виртуальную функцию можно использовать, даже если у её класса нет производных классов. Производный класс, который не нуждается в собственной версии виртуальной функции, не обязан её переопределять.
Интерпретация вызова виртуальной функции зависит от типа объекта, для которого она вызывается, в то время как интерпретация вызова невиртуальной функции-члена класса зависит от типа указателя или ссылки, указывающей на этот объект.
Этот механизм делает производные классы и виртуальные функции ключевыми понятиями при разработке программ на С++. Базовый класс определяет интерфейс, для которого производные классы обеспечивают набор реализаций. Указатель на объект класса может передаваться в контекст, где известен интерфейс, определённый одним из его базовых классов, но этот производный класс неизвестен. Механизм виртуальных функций гарантирует, что этот объект всё равно будет обрабатываться функциями, определёнными для него, а не для базового класса.
4.4 Абстрактный класс
Абстрактный класс в объектно-ориентированном программировании — класс, содержащий хотя бы один абстрактный метод. Абстрактный метод не реализуется для класса, в котором описан, однако должен быть реализован для его неабстрактных потомков. Класс является абстрактным, если он содержит хотя бы одну чистую виртуальную функцию.
Чисто виртуальной функцией называется виртуальная функция, указанная с инициализатором =0
Например:
virtual void F1(int) =0;
Объявление класса может содержать виртуальный деструктор, используемый для удаления объекта определенного типа. Однако виртуального конструктора в языке С++ не существует. Некоторой альтернативой, позволяющей создавать объекты заданного типа, могут служить виртуальные методы, в которых выполняется вызов конструктора для создания объекта данного класса.
Механизм абстрактных классов служит для представления общих понятий, которые фактически используются лишь для порождения более конкретных понятий. Абстрактный класс можно также употреблять как определение интерфейса, в котором производные классы обеспечивают разнообразие реализаций.
