- •Доступ к наследуемым членам.
- •Статусы доступа при наследовании классов
- •Начальная часть таблицы, выводимой по этой программе, имеет вид:
- •Полиморфизм. Механизм виртуальных функций. Привести примеры.
- •34. Абстрактный класс. Чисто виртуальные функции
- •36. Шаблоны классов. Форматы описания шаблона класса, методов и объектов шаблонного класса.
- •Жизненный цикл программы.
Начальная часть таблицы, выводимой по этой программе, имеет вид:
Полиморфизм. Механизм виртуальных функций. Привести примеры.
Полиморфизм – взаимозаменяемость объектов с одинаковым интерфейсом. Язык программирования поддерживает полиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию – например , реализация класса может быть изменена в процессе наследования. Полиморфизм – один из четырех важнейших механизмов ООП (наряду с абстракцией, инкапсуляцией наследованием).
Полиморфизм позволяет писать более абстрактные программы и повысить коэффициент повторного использования кода. Общие свойства объектов объединяются в систему, которую могут называть по-разному — интерфейс, класс. Общность имеет внешнее и внутреннее выражение:
внешняя общность проявляется как эквивалентный набор методов с одинаковыми именами или совпадающими сигнатурами (именами методов, типами аргументов и их количеством);
внутренняя общность — одинаковая функциональность методов. Её можно описать интуитивно или выразить в виде строгих законов, правил, которым должны подчиняться методы. Возможность приписывать разную функциональность одному методу (функции, операции) называется перегрузкой метода (перегрузкой функций, перегрузкой операций).
Механизм виртуальных функций.
Student s; Person &p = s; s.name(); //Student::name() p.name(); //Person::name()
В 3-й строке вызовется метод класса Student, т.к. s является объектом этого класса. Однако, в строке 4 вызовется метод name базового класса Person, хотя по логике следовало бы тоже ожидать вызов name() класса Student — ведь p — это ссылка на объект производного класса.
Возможность вызова методов производного класса через ссылку или указатель на базовый класс осуществляется с помощью механизма виртуальных функций. Чтобы при вызовеp.name() вызвался метод класса Student, реализуем классы следующим образом:
struct Person { virtual string name() const; }; struct Student: Person { string name() const; };
Перед методом name класса Person мы указали ключевое слово virtual, которое указывает, что метод является виртуальным. Теперь при вызове p.name() произойдет вызов метода класса Student, несмотря на то, что мы его вызываем через ссылку на базовый класс Person. Аналогичная ситуация и с указателями:
Student s; Person *p = &s ; p->name(); //вызовется Student::name(); Person n; p = &n; p->name(); //вызовется Person::name()
Если с некоторого класса в иерархии наследования метод стал виртуальным, то во всех производных от него классах он будет виртуальным, вне зависимости от того, указано ли ключевое слово virtual в классах наследниках.
Механизм виртуальных функций реализует полиморфизм времени выполнения: какой виртуальный метод вызовется будет известно только во время выполнения программы.
В качестве следующего примера можно рассмотреть класс TextFile, от которого наследуются два класса: GZippedTextFile и BZippedTextFile. Базовый класс имеет два метода:name(), возвращающий имя файла, и read(), считывающий данные из файла. В этом случае виртуальным имеет смысл сделать только метод read, т.к. у каждого типа сжатого файла будет свой способ считывания данных:
struct TextFile { string name() const; virtual string read(size_t count); //... }; struct GZippedTextFile : TextFile { string read(size_t count); //... } struct BZippedTextFile : TextFile { string read(size_t count); //... }
