Четвертый BORLAND С++ и его окружение

       

Позднее связывание с использованием виртуальных функций элементов


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

вызов от другого по типу их аргументов. Используя эту информацию, он

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

другого, при наличии аргументов одного типа на этапе выполнения, и

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

Именно использование ключевого слова virtual приводит к отсрочке связывания, и вызову нужной функции на этапе выполнения.

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

даже в предке, если она вызывается для потомка. В отличии от раннего

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

Синтаксис определения виртуальных функций элементов очень прозрачный: добавьте слово virtual к первому определению функции элементу:

virtual void Show();

virtual void Hide();

Внимание! Только встроенные функции элементы могут быть объявлены как виртуальные. Как только функция объявлена виртуальной, она не



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

перечнем аргументов, но с другим типом возвращаемого значения. Если

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

Вы можете свободно переопределять Show с другим перечнем разнотипных аргументов (изменяя при этом тип возвращаемого значения или

нет), но виртуальный механизм не задействуется для такой версии Show.

Какая именно функция элемент Show будет вызвана - зависит только

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

Circle ACircle

Point* APoint_рointer = &ACircle; // указатель на Circle,

// которому присваивается

// значение указателя на

// базовый класс, Point

APoint_рointer->Show(); // вызывает Circle::Show!

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

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

противном случае, нужно пользоваться виртуальными.



Содержание раздела