Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Виртуальные методы, механизм позднего связывания.
Виртуальные методы Работа с объектами чаще всего производится через указатели. Указателю на базовый класс можно присвоить значение адреса объекта любого производного класса, например: / / Описывается указатель на базовый класс: monstr *р; / / Указатель ссылается на объект производного класса: р = new daemon: Вызов методов объекта происходит в соответствии с типом указателя, а не фактическим типом объекта, на который он ссылается, поэтому при выполнении оператора, например, p->draw(l. 1. 1. 1): будет вызван метод класса monstr, а не класса daemon, поскольку ссылки на методы разрешаются во время компоновки программы. Этот процесс,называется ранним связыванием. Чтобы вызвать метод класса daemon, можно использовать явное преобразованиетипа указателя: (daemon * p)->draw(l. 1. 1. 1); Это не всегда возможно, поскольку в разное время указатель может ссылаться на объекты разных классов иерархии, и во время компиляции программы конкретный класс может быть неизвестен. В качестве примера можно привести функцию, параметром которой является указатель на объект базового класса. На его место во время выполнения программы может быть передан указатель на любой производный класс. Другой пример — связный список указателей па различные объекты иерархии, с которым требуется работать единообразно. В C++ реализован механизм позднего связывания, когда разрешение ссылок на метод происходит на этапе выполнения программы в зависимости от конкретного типа объекта, вызвавшего метод. Этот механизм реализован с помощью виртуальных методов и рассмотрен в следующем разделе. Для определения виртуального метода используется спецификатор virtual, например: virtual void draw(int х. int у. int scale, int position); Рассмотрим правила описания и использования виртуальных методов. • Если в базовом классе метод определен как виртуальный, метод, определенный в производном классе с тем же именем и набором параметров, автоматически становится виртуальным, а с отличающимся набором параметров — обычным. • Виртуальные методы наследуются, то есть переопределять их в производном классе требуется только при необходимости задать отличающиеся действия. Права доступа при переопределении изменить нельзя. • Если виртуальный метод переопределен в производном классе, объекты этого класса могут получить доступ к методу базового класса с помощью операции доступа к области видимости. • Виртуальный метод не может объявляться с модификатором static, но может быть объявлен как дружественный. • Если в классе вводится описание виртуального метода, он должен быть определен хотя бы как чисто виртуальный. Чисто виртуальный метод содержит признак» О вместо тела, например: virtual void f(int) = 0; Чисто виртуальный метод должен переопределяться в производном классе (возможно, опять как чисто виртуальный). Если определить метод draw в классе raonstr как виртуальный, решение о том, метод какого класса вызвать, будет приниматься в зависимости от типа объекта, на который ссылается указатель: monstr * г. *р; г = new monstr;. // Создается объект класса monstr р = new daemon; // Создается объект класса daemon r->draw(l. 1. 1. 1); // Вызывается метод monstr::draw p->draw(l. 1. 1. 1); // Вызывается метод daemon::draw р-> monstr: rdrawd, 1. 1. 1); // Обход механизма виртуальных методов Если объект класса daemon будет вызывать метод draw не непосредственно, а косвенно (то есть из другого метода, определенного в классе monstr), будет вызван метод draw класса daemon. Итак, виртуальным называется методу ссылка на который разрешается на этапе выполнения программы (перевод красивого английского слова virtual — в данном значении всего-навсего «фактический», то есть ссылка разрешается по факту вызова). class Ancestor { public: virtual void function1 () { cout << "Ancestor::function1()" << endl; } void function2 () { cout << "Ancestor::function2()" << endl; } };
class Descendant: public Ancestor { public: virtual void function1 () { cout << "Descendant::function1()" << endl; } void function2 () { cout << "Descendant::function2()" << endl; } };
Descendant* pointer = new Descendant (); Ancestor* pointer_copy = pointer;
pointer->function1 (); pointer->function2 ();
pointer_copy->function1 (); pointer_copy->function2 (); В этом примере класс Ancestor определяет две функции, одну из них виртуальную, другую — нет. Класс Descendant переопределяет обе функции. Однако, казалось бы одинаковое обращение к функциям даёт разные результаты. На выводе программа даст следующее: Descendant::function1() Descendant::function2() Descendant::function1() Ancestor::function2()
Date: 2016-07-25; view: 519; Нарушение авторских прав |