Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
С++ - ООП.doc
Скачиваний:
15
Добавлен:
21.09.2019
Размер:
399.87 Кб
Скачать

Виртуальные функции

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

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

Рассмотрим пример:

class Base {

public:

virtual void show(void)

{ cout << “В базовом класее Base\n;}

};

class Derive:public Base{

void show(void)

{ cout<<”В производном классе Derive\n”;}

};

class Derive1:public Derive{

void show(void)

{ cout<<”В производном классе Derive1\n”;}

};

class Derive2:public Derive1{

void show(void)

{ cout<<”В производном классе Derive2\n”;}

};

void main(void)

{

Base bobj, *pb;

Derive dobj, *pd;

Derive1 d1obj, *pd1;

Derive2 d2obj, *pd2;

pb=&bobj;

pb->show(); // вызов функции show() класса Base

pd=&dobj; // вызов функции

pd->show(); // show() класса Derive виртуальность функции не исп.

pd1=&d1obj; // вызов функции

pd1->show(); // show() класса Derive1

pd2=&d2obj; // вызов функции

pd2->show(); // show() класса Derive2

pb=&dobj; // указателю на базовый класс присвоен

// адрес производного класса Derive

pb->show(); // вызов show() класса Derive, исп. Механизм вирт. Функций

pb=&d1obj; // указателю на базовый класс присвоен

// адрес производного класса Derive1

pb->show(); // вызов show() класса Derive1

pd1=&d2obj; // указателю на базовый класс Derive1 присвоен

// адрес производного класса Derive2

pd1->show(); // вызов функции show() класса Derive2

// работает механизм виртуальных функций

pd1->Base::show(); // Явный вызов функции show() класса Base!

pd1->Derive::show(); // Явный вызов функции show() класса Derive!

((Derive2 *)pb)->show(); // Вызов функции show() класса Derive2

}

Замечания к использованию виртуальных функций

Виртуальная функция должна быть членом класса. Она не может быть дружественной для класса, в котором определена, но - дружественной к другому классу. Функция, которая объявлена виртуальной, остается виртуальной не зависимо от того, сколько производных классов построено. Если в рассмотренном примере класс Derive1 будет производным классом для Derive, а не для Base, то функция show() в классе Derive1 остается виртуальной. Если в производном классе функция не замещает виртуальную, так как она не объявлена или имеет другой прототип, то вызывается функция базового класса.

Виртуальные функции удобны для использования, так как в общем случае, базовый класс задает основной интерфейс, который будут иметь производные классы, а производные классы задают свой метод. Для описания полиморфизма часто используется понятие “один интерфейс, много методов”. Так как ООП позволяет создавать сложные программы, то при корректном построении производных классов все объекты, начиная с базового класса, доступны с помощью одного и того же метода, то нужно помнить только интерфейс. Отделение интерфейса от наполнения функций позволяют создавать классы библиотек (class libraries).

Вызов виртуальной функции реализуется как непрямой вызов по таблице виртуальных функций класса. Таблицу создает компилятор, а связывание происходит во время выполнения. Термин позднее связывание (late binding)