Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык программирования С++ и его «подводные камни».DOC
Скачиваний:
44
Добавлен:
01.05.2014
Размер:
1.02 Mб
Скачать

3.2. Виртуальные функции –полиморфизм

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

class BaseClass

{

public: void Method ( );

}

class DrivedClass: public BaseClass

{

public:

void Method ( );

};

void SimpleFunc (BaseClass * ptrBase)

{

ptrBase->Method ( );

}

А теперь попробуйте ответить на вопрос: «К какому методу относится вызов в функции SimpleFunc( )?» Правильно, к методу базового класса. И для того, чтобы вызвать метод производного класса, необходимо использование операции разрешения контекста.

Что же делать, чтобы иметь возможность вызывать оба метода? Ответ на этот вопрос дает полиморфизм – использование одного и того же вызова для ссылки на разные методы в зависимости от типа объекта. Для поддерж­ки полиморфизма язык программирования должен поддерживать механизм позднего связывания, при котором решение о том, какой именно метод с од­ним и тем же именем должен быть вызван, принимается в зависимости от типа объекта ужево время выполнения программы.

Обычная практика выбора вызываемого метода на этапе компиляции назы­вается ранним связыванием.

В С++ имеется ключевое слово virtual, использование которого перед именем метода предполагает, что все вызовы этого метода (и всех методов с этим именем в общих производных классах) должны вы­пол­нять­ся посредством механизма позднего связывания. Небольшое изменение в предыдущем примере снимает вопрос о неоднозначности вызываемого метода:

class BaseClass

{

public: virtual void Method ( ); // Методобъявленвиртуальным

};

class DrivedClass: public BaseClass

{

public:

void Method ( );

};

void SimpleFunc (BaseClass * ptrBase)

{

ptrBase->Method ( );

}

Теперь соответствующий метод будет вызываться в зависимости от того, указатель на какой объект передается в функцию SimpleFunc..

Примечание

1. Если метод объявлен виртуальным – он не может быть перегружен.

2. Виртуальный метод, чаще называемый виртуальной функцией, не может быть статическим.

В каких же случаях следует использовать виртуальные функции, учи­ты­вая, механизм позднего связывания требует дополнительных расходов вре­мени на вызов метода? Общее правило следующее: если существует вероят­ность, что в некотором производном классе будет использован метод, пере­крывающий метод базового класса и которому нужен доступ к компонентам этого базового класса, то он должен быть виртуальным.

Может быть объявлен и виртуальный деструктор, что позволяет использовать механизм позднего связывания при определении де­струк­то­ра, вызывае­мого для удаления объекта.

С виртуальными функциями тесно связано понятие абстрактного класса — такого, который содержит как минимум одну чистую виртуальную функцию.Чистая виртуальная функция – это функция, определенная со спецификатором = 0, и для которой нет и не пла­ни­ру­ет­ся какой-либо реализации. Объявление такой функции имеет вид:

virtual void Method ( ) = 0; // Чистая виртуальная функция

Такие функции должны быть определены в производном классе, иначе и производный класс будет абстрактным.

Абстрактные классы чрезвычайно полезны для организации иерар­хи­че­ской структуры классов, когда базовый класс определяет некоторое общее по­ведение, а некоторые частные особенности переносятся в конкретные про­изводные классы.

Примечание

Нельзя создавать объекты абстрактного класса – он может быть использован только в качестве базового для построения других классов. Однако указатель на абстрактный класс создавать можно.