Правила наследования различных методов.

      Комментарии к записи Правила наследования различных методов. отключены

Конструкторы и деструкторы не наследуются. Производный класс должен иметь собственные конструкторы.

Порядок вызова конструкторов:

  • Eсли в конструкторе производного класса явный вызов конструктора базового класса отсутствует, автоматически вызывается конструктор по умолчанию базового класса (как в первом конструкторе класса daemon).
  • Если конструктор базового класса требует указания параметров, он должен быть явным образом вызван в конструкторе производного класса в списке инициализации (как в трех последних конструкторах).
  • Для иерархии из нескольких уровней, конструкторы базовых классов вызываются, начиная с самого верхнего уровня. После этого выполняются конструкторы элементов класса, которые являются объектами, в порядке их объявления в классе, а затем исполняется конструктор класса.
  • В случае нескольких базовых классов их конструкторы вызываются в порядке объявления.

Правила наследования деструкторов:

  • Eсли в производном классе не описан деструктор, он формируется по умолчанию и вызывает деструкторы всех базовых классов;
  • В отличие от конструкторов, в деструкторе производного класса не требуется явно вызывать деструкторы базовых классов (это будет сделано автоматически);
  • Для иерархии классов из нескольких уровней, деструкторы вызываются в порядке обратном вызову конструкторов (сначала вызывается деструктор класса, затем — деструкторы элементов класса, а потом деструктор базового класса).

<p>Не наследуется операция присваивания, требуется явно определить ее в производном классе.

В теле функции-операции производного класса должен применяться явный вызов функции-операции присваивания из базового класса.

Вызов функций базового класса предпочтительнее копирования фрагментов кода из функций базового класса в функции производного. Этим достигается сокращение объема кода и упрощение модификации программы (изменения требуется вносить только в одну точку программы).

Тема 2.13

Виртуальные методы и абстрактные классы

Виртуальные методы

Работа с объектами чаще всего производится через указатели. Указателю на базовый класс можно присвоить значение адреса объекта любого производного класса, например:

monstr *р; // Описывается указатель на базовый класс

р = new daemon; // Указатель ссылается на объект производного класса

Вызов методов объекта происходит в соответствии с типом указателя, а не фактическим типом объекта, на который он ссылается. Например, при выполнении оператора

p-draw(l, 1, 1, 1);

будет вызван метод класса monstr, а не класса daemon.

Это обусловлено тем, что ссылки на методы разрешаются во время компоновки программы. Этот процесс, называется ранним связыванием.

Чтобы вызвать метод производного класса, можно использовать явное преобразование типа указателя:

(daemon * p)-draw(l, 1, 1, 1);

Это не всегда возможно, т.к. в разное время указатель может ссылаться на объекты разных классов иерархии, и во время компиляции программы конкретный класс может быть неизвестен. Примером может быть функция, параметром которой является указатель на объект базового класса. На его место во время выполнения программы может быть передан указатель на любой производный класс. Другой пример — связный список указателей па различные объекты иерархии, с которым требуется работать единообразно.

Для решения данной проблемы предназначен механизм позднего связывания, когда разрешение ссылок на метод происходит на этапе выполнения программы в зависимости от конкретного типа объекта, вызвавшего метод. Этот механизм реализован с помощью виртуальных методов.

Для определения виртуального метода используется спецификатор virtual:

virtual void draw(int х, int у, int scale, int position);

Правила описания и использования виртуальных методов:

  • Если в базовом классе метод определен как виртуальный, метод, определенный в производном классе с тем же именем и набором параметров, автоматически становится виртуальным, а с отличающимся набором параметров – обычным.
  • Виртуальные методы наследуются, переопределять их в производном классе требуется только при необходимости задать отличающиеся действия. Права доступа при переопределении изменить нельзя.
  • Если виртуальный метод переопределен в производном классе, объекты этого класса могут получить доступ к методу базового класса с помощью операции доступа к области видимости.
  • Виртуальный метод не может объявляться с модификатором static, но может быть объявлен как дружественный.
  • Если в классе вводится описание виртуального метода, он должен быть определен хотя бы как чисто виртуальный.

Чисто виртуальный метод содержит признак = 0 вместо тела, например:

virtual void f(int) = 0;

Чисто виртуальный метод должен переопределяться в производном классе (возможно, опять как чисто виртуальный).

Если определить метод draw в классе monstr как виртуальный, решение о том, метод какого класса вызвать, будет приниматься в зависимости от типа объекта, на который ссылается указатель:

monstr * r, *р;

r = new monstr; // Создается объект класса monstr

р = new daemon; // Создается объект класса daemon

r-draw(l, 1, 1, 1); // Вызывается метод monstr::draw

p-draw(l, 1, 1, 1); // Вызывается метод daemon::draw

р- monstr::draw (1, 1, 1, 1); // Обход механизма виртуальных методов

Если объект класса daemon будет вызывать метод draw не непосредственно, а косвенно (т.е. из другого метода, определенного в классе monstr), будет вызван метод draw класса daemon.

Виртуальным называется метод, ссылка на который разрешается на этапе выполнения программы.

Статьи к прочтению:

Наследование недвижимости. Порядок наследования недвижимости


Похожие статьи: