- •Преобразование типов указателей
- •Операторы определения адреса и обращения по адресу
- •Указатели на константы и константные указатели
- •Арифметические действия с указателями
- •Одномерные и многомерные массивы.
- •Строки символов. Основные функции для работы со строками.
- •Перечисление.
- •Структура.
- •Объединения.
- •Битовые поля.
- •Тип данных bool. Тип данных wchar_t.
- •Способы передачи параметров в подпрограммы.
- •Операторы распределения памяти.
- •Объявление typedef.
- •Оператор sizeof.
- •Передача аргументов по умолчанию.
- •Встроенные функции.
- •Определение пространства имён.
- •Оператор разрешения области видимости.
- •Объявление «using». Директива «using». Псевдонимы.
- •Механизм обработки исключений.
- •Вложенные исключения.
- •Определение класса.
- •Указатель this. Спецификаторы доступа к членам класса.
- •«Друзья» класса.
- •Конструктор класса. Список инициализации.
- •Конструктор по умолчанию.
- •Конструктор копирования.
- •Явные конструкторы.
- •Деструкторы.
- •Встроенные функции–члены класса. Статические члены класса.
- •Функции-члены класса с квалификаторами const и volatile.
- •Вложенные классы. Локальные классы.
- •Общие правила перегрузки операторов.
- •Перегрузка оператора присваивания.
- •Оператор индексирования [].
- •Перегрузка бинарных операторов.
- •Составные операторы присваивания.
- •Оператор вызова функции.
- •Операторы преобразования типов (конверторы).
- •Структура данных – стек.
- •Структура данных – очередь.
- •Деревья.
- •Наследование
- •Доступ к членам наследуемого класса
- •Конструкторы, деструкторы и наследование
- •Наследование и присваивание.
- •Виртуальные функции.
- •Полиморфизм и позднее связывание.
- •Передача аргументов по умолчанию в виртуальные функции.
- •Виртуальные деструкторы.
- •Абстрактные классы.
- •Множественное наследование.
- •Виртуальное наследование.
Полиморфизм и позднее связывание.
Возможность вызова виртуальных функций производных классов через указатель или ссылку на базовый класс называется полиморфизмом подтипов или просто полиморфизмом. Класс, который содержит или наследует виртуальную функцию, называется полиморфным классом.
Термин позднее или отложенное или динамическое связывание относится к тому обстоятельству, что компилятор не может определить, какая виртуальная функция должна вызываться, если к ней обращаются через указатель или ссылку на базовый класс. Эта особенность виртуальных функций приводит к тому, что адрес нужной виртуальной функции может быть определён только во время исполнения программы. Позднее связывание реализуется следующим образом:
для каждого полиморфного класса компилятор строит таблицу адресов виртуальных функций vtable;
каждый объект полиморфного класса содержит скрытый указатель vptr на таблицу адресов виртуальных функций;
компилятор автоматически вставляет в начало конструктора полиморфного класса фрагмент кода, который инициализирует vptr;
при вызове виртуальной функции, её адрес извлекается из таблицы vtable, на которую указывает vptr объекта.
Передача аргументов по умолчанию в виртуальные функции.
Механизм виртуальных функций не поддерживает передачу аргументов по умолчанию в такие функции, т.е. если функция производного класса вызывается через указатель или ссылку на базовый класс, то ей передаются аргументы по умолчанию, указанные в базовом классе. Это обусловлено тем, что аргументы по умолчанию определяются на этапе компиляции. Приведём пример передачи аргументов по умолчанию виртуальным функциям:
Виртуальные деструкторы.
Т.к. объекты производных классов могут уничтожаться через указатели на базовые классы при помощи оператора delete, то деструкторы можно объявлять виртуальными в отличие от конструкторов. Общее правило таково: если класс является полиморфным, то его деструктор должен быть виртуальным, причем этот деструктор всегда должен иметь реализацию, т.к. он может быть вызван из деструктора производного класса.
Абстрактные классы.
Виртуальная функция называется чистой (pure), если она определена только как спецификатор интерфейса, т.е. не имеет реализации. Чисто виртуальные функции имеют следующий прототип:
virtual имя_функции (параметры) = 0;
Как правило, чисто виртуальные функции определяются в производных классах. Класс, который содержит хотя бы 1 чисто виртуальную функцию, называется абстрактным классом. Такой класс может использоваться только в качестве базового класса для других классов. Т.к. у чисто виртуальных функций отсутствует реализация, то невозможно создать объект, принадлежащий абстрактному классу. Отсюда следует, что абстрактные классы подчиняются следующим требованиям:
абстрактный класс не может использоваться в качестве аргумента или типа возвращаемого функцией значения;
абстрактный класс нельзя использовать в явном преобразовании типов;
Можно определить указатель или ссылку на абстрактный класс. Это позволит использовать абстрактные классы для описания интерфейсов базовых классов и работы с производными классами через указатели или ссылки на базовый класс. Если класс, производный от абстрактного класса, не определяет все чисто виртуальные функции, то он также является абстрактным классом. Т.к. деструктор абстрактного класса может быть вызван компилятором при уничтожении объекта производного класса, то деструктор абстрактного класса должен быть определён как виртуальная функция с пустым телом, а не как чисто виртуальная функция.