29 Виртуални функции и класове
Виртуалните функции са функции-членове на класа, които се извикват по време на изпълнение на програмата (т.е. динамично) според типа на обекта, с който се използва.
Например базовият клас може да опише фигура на екрана, без да уточнява външния й вид, докато производните класове (кръг, елипса и т.н.) уникално дефинират нейната форма и размер. Ако въведете функция в базовия клас за показване на фигура на екрана, тогава изпълнението на тази функция ще бъде възможно само за обекти от всеки от производните класове, които дефинират конкретни изображения.
Декларация на виртуална функция в клас:
Имайте предвид, че класовете, които включват такива функции, играят специална роля в обектно-ориентираното програмиране. Затова имат специално наименование – полиморфни.
Нека се върнем към примера с фигура, споменат по-горе. Помислете за класа Point
class Point: публично местоположение
Точка (int nx, int ny);
виртуална празнота Show();
виртуална празнота Hide();
виртуална празнота Drag(int by);
Не всички функции могат да бъдат виртуални, а само нестатични компонентни функции от някакъв клас. След като дадена функция е дефинирана като виртуална, предефинирането й в производен клас (със същия прототип) създава нова виртуална функция в този клас, без да се използва виртуалният спецификатор.
Произведен клас не може да дефинира функция със същото име и същия подпис на параметър, но с различен тип връщане от виртуална функция на базовия клас. Това води до грешка по време на компилиране.
Ако въведете функция в производен клас със същото име и тип връщане като виртуалната функция на базовия клас, но с различен подпис на параметър, тогава тази функцияпроизводният клас няма да бъде виртуален. В този случай, използвайки указател към базовия клас, с произволна стойност на този указател се извиква функцията на базовия клас (въпреки виртуалния спецификатор и наличието на подобна функция в производния клас).
Помислете как ще изглежда извикването на виртуалната функция void Show () в производния клас:
клас Circle : публична точка
Кръг (int nx, int ny, int nr);
void Expand(int by);
недействителен договор ( int by ); >;
Както виждаме, виртуалният спецификатор вече не може да бъде посочен.
Механизмът за виртуално повикване може да бъде потиснат чрез изричното използване на напълно квалифицираното име. По този начин, ако е необходимо да се извика виртуален метод (компонентна функция) на базовия клас от производен клас, се използва пълното име.
Всичко по-горе може да се комбинира в ПРАВИЛА:
1) не декларирайте статичен;
2) Декларациите на виртуални функции в производните класове трябва да имат същата сигнатура като в базовия клас. Указването на виртуалния спецификатор не е задължително в този случай.
3) Виртуалната функция трябва задължително да бъде дефинирана или да бъде чиста виртуална функция.
Чиста виртуална функция е компонентна функция, която има следната дефиниция:
виртуален тип име на функция (списък с формални параметри)=0;
В тази нотация конструкцията "=0" се нарича "чист спецификатор". Пример за описание на чисто виртуална функция:
виртуална празнота F()=0;
Чиста виртуална функция в дефиниция на клас показва, че нейната дефиниция е отложена към производни класове. Една чисто виртуална функция "не прави нищо" и не е достъпна за разговори. Целта му е да служи като основа за функциите, които го заменят впроизводни класове и показват, че дадения клас е абстрактен. Виртуални класни стаи
При такова наследяване може да възникне проблем при наследяването на два екземпляра на полета от клас A в клас D до B и C (ще бъде заета допълнителна памет и ще възникне объркване). За да избегнете това, трябва да декларирате класа виртуален, когато създавате B и C.
клас B: виртуална публика A
клас D: публичен C, публичен B
В този случай последователността при създаване на обекти от клас D ще бъде следната: първо се извиква конструкторът от клас A (извиква се веднъж), след това конструкторите B и C, последният е конструкторът от клас D. Унищожаването на обекти от клас D се извършва в обратен ред.