Понятие виртуальной функции

Что такое друзья класса

Что такое статический элемент класса

Обращение к компонентам объекта

Определение объекта класса по имени и с помощью указателя и динамического выделения памяти

13) Что такое конструкторы и деструкторы. Какие типы конструкторов вы знаете?

14) Когда необходимо описывать конструктор копирования?

Полиморфизм

Как понятие полиморфизм – это множество форм.

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

Многие авторы (Подбельский В.В.) под полиморфизмом понимают механизм виртуальных функций.

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

Но это просто механизм замещения.

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

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

Виртуальной может быть только нестатическая компонентная функция.

class A {

public:

virtual void F1 ();

virtual int F2 (char*);

};

class B: public A {

public:

virtual void F1 ();

virtual int F2 (char*);

};

class C: public A {

public:

void F1 ();

int F2 (char*);

};

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

Указатель на базовый класс может принимать конкретные значения.

-Если этот указатель к моменту вызова функции указывает на объект базового класса, вызывается вариант функции из базового класса.

-Если этот указатель указывает на некоторый объект производного класса (фактически указывает на данные базового класса в объекте производного класса), то вызывается вариант функции из производного класса.

Void main () {

A * ap = new A;

B * bp = new B;

C * cp = new C;

ap-> F1 (); // вызов функции базового класса А

ap = bp;

ap-> F1 (); // вызов замещенной функции класса В

ap = cp;

ap -> F1 (); // вызов замещенной функции класса С

}

Вызов виртуальной функции через указатель на базовый класс позволяет в зависимости от значения этого указателя (не от типа этого указателя, а от значения!) вызывать варианты этой функции из разных классов.

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

Если из текста программы однозначно следует какая функция вызывается, компилятор включает в текст оператор call c именем функции, компоновщик заменяет имя на фактический адрес функции.

Такой процесс вызова функции носит название раннего связывания.

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

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

Для реализации динамического связывания компилятор создает таблицу виртуальных методов (vtbl), а к каждому объекту добавляет скрытое поле ссылки (vptr) на таблицу vtbl.

Применена технология использования информации о типе на этапе выполнения, или сокращенно RTTI — Run-Time Туре Information. Дело в том, что заранее (на этапе компиляции) не известно, объекты каких типов будут передаваться в качестве аргумента данного метода на указатель или ссылку базового класса.

Классы, включающие виртуальные функции, играют особую роль в объектно-ориентированном программировании. Они носят название полиморфных классов.

Механизм виртуальных функций в ООП обеспечивает большую гибкость при использовании уже готовых библиотек классов, а также существенно увеличивает возможности программиста.

Преобразование типов в иерархии классов

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

ap = bp;

В этом предложении осуществляется неявное преобразование типа “указателя на В” в “указатель на А”, а затем значение bp присваивается ap.

Рассмотрим два класса, связанных отношениями наследования:

class A {

protected:

int a1, a2;

public:

void func_a ();

};

class B: public A {

int b1, b2;

public:

void func_b ();

};

A* ap = new A;

B* bp = new B;


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: