Віртуальні функції та класи

Віртуальні функції

У всіх прикладах, наведених раніше, повідомлення, яке посилалось об'єкту, пов'язувалося з конкретним методом на етапі компіляції. Раннє зв'язування має переваги, що стосуються оптимальності коду. Поряд з раннім, у багатьох об'єктно-орієнтованих мовах підтримується механізм пізнього зв'язування, коли повідомлення зв'язується з конкретним методом на етапі виконання програми. Іншими словами, визначається набір різних реакцій об'єкта на одне й те саме повідомлення, а вже конкретна реакція – на етапі виконання програми.

Розглянемо, як реалізована в С++ концепція поліморфізму за допомогою механізму віртуальних функцій. Віртуальна функція – це специфічна функція-член класу, яка визначається в базовому класі, а потім перевизначаться в похідних. Сукупність класів, у яких визначається та перевизначаться конкретна віртуальна функція, називається поліморфічним кластером, асоційованим з даною віртуальною функцією.

Підтримка механізму віртуальних функцій у C++ забезпечується специфічною властивістю покажчика на клас. Ця властивість полягає в тому, що покажчик на базовий клас може вказувати не тільки на його об'єкт, але й на об'єкти будь-якого public -похідного класу. Наприклад:

class Value {

protected:

int value;

public:

Value(int n)

{value=n;}

Int Getvalue(void)

{return value;}};

Визначимо похiдний клас:

Class Mult:public Value

{

protected:

int mult;

public:

Mult(int n,int m):

Value(n)

{mult=m;}

Int GetValue(void)

{return value*mult;}

Main()

{Value*base;

base=Mult(10,2)

cout<<base->GetValue;}

//тут буде надрукованo 10 за рахунок

//механiзму раннього зв'язування

Віртуальна функція – це звичайна функція-член класу, яка відрізняється від інших лише наявністю ключового слова virtual перед її оголошенням:

virtual int GetValue(){//...}

Якщо оголосити функцію GetValue() в обох класах як віртуальну, то в наведеному вище прикладі буде надруковано 20. Оголошення функції GetValue() як віртуальної за допомогою спеціального механізму дозволяє через покажчик на базовий клас викликати функції тих похідних класів за ієрархією, адреси яких покажчик містить у даний момент.

Оскільки віртуальна функція є членом класу, то її визначення може знаходитися за межами формального опису класу. При цьому при визначенні функції ключове слово virtual не потрібне. У межах формального опису класу може бути оголошена віртуальна функція

virtual int GetValue();

Тоді за межами формального опису

int Value::GetValue(){return value;}

Однак чи потрібне ключове слово virtual при оголошенні функції в усіх членах поліморфічного кластера? Виявляється, що достатньо його наявності лише в першому члені поліморфічного кластера, перед віртуальною функцією найвищого рівня.

Розглянемо приклад використання віртуальних функцій. Нехай потрібно написати програму виведення на екран різних геометричних фігур. Причому проблема полягає в тому, що ми взагалі не знаємо на даному етапі, скільки фігур буде, як їх будувати. Однак усі фігури мають спільну властивість – вони геометричні. Використаємо цей факт, написавши деякий клас Form:

class Form {

public:virtual void Draw() { };};

Далі можемо визначити масив покажчиків на Form:

Form*picture[100];

Для побудови конкретної фігури визначатимемо класи, похідні від Form, які містять віртуальні функції Draw(). За такого підходу main() -функцію можемо написати одразу, не чекаючи опису конкретних класів з функціями, що створюють фігури:

Main()

{int i=0;

while(i<100&& picture[i]!=0)

{picture[i]->Draw();i+=1}}

Основну програму складено. Тепер можемо писати похідні класи:


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



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