Для чого потрібні віртуальні функції, програмування на c і ​​c

Як зазначалося раніше, віртуальні функції в комбінації з похідними типами дозволяють мови С ++ підтримувати поліморфізм часу виконання. Цей поліморфізм ва-дружин для об'єктно-орієнтованого програмування, оскільки він дозволяє переопреде-лять функції базового класу в класах-нащадках з тим, щоб мати їх версію стосовно до даного конкретного класу. Таким чином, базовий клас визначає загальний інтерфейс, кото-рий мають всі похідні від нього класи, і в той же час поліморфізм дозволяє похідним класам мати свої власні реалізації методів. Завдяки цьому поліморфізм часто визна-ділячи фразою «один інтерфейс - безліч методів».

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

Наявність загального інтерфейсу і його множинної реалізації є важливим остільки, оскільки допомагає програмістам розробляти складні програми. Наприклад, доступ до всіх об'єктів, похідним деякого базового класу, здійснюється однаковим способом, навіть якщо реальні дії цих об'єктів відрізняються при переході від одного похідного класу до іншого. Це означає, що необхідно запам'ятати тільки один інтерфейс, а не НЕ-скільки. Більш того, відділення інтерфейсу від реалізації дозволяє створювати бібліотеки клас-сов, що поставляються незалежними розробниками. Якщо ці бібліотеки реалізовані коректно,
то вони забезпечують загальний інтерфейс, і їх можна використовувати для виведення своїх власних специфічних класів.

Щоб зрозуміти всю міць ідеї «один інтерфейс - безліч методів», розглянемо дотримуюся-щую коротку програму. Вона створює базовий клас figure. Цей клас використовується для збер-ня розмірів різних двовимірних об'єктів і для обчислення їх площ. Функція set_dim () є стандартною функцією-членом, оскільки її дії є спільними для всіх вироб-водних класів. Однак функція show_area () оголошується як віртуальна функція, оскільки спосіб обчислення площі кожного об'єкта є специфічним. Програма використовує клас figure для виведення двох специфічних класів square і triangle.

#include
class figure protected:
double x, y;
public:
void set_dim (double i, double j) x = i;
у = j;
>
virtual void show_area () cout <<"No area computation defined ";
cout <<"for this class. \n";
>
>;
class triangle: public figure public:
void show_area () cout <<"Triangle with height ";
cout < cout <<" has an area of ";
cout <>
>;
class square: public figure public:
void show_area () cout <<"Square with dimensions ";
cout < cout <<" has an area of ";
cout <>
>;
int main ()
figure * p; / * Створення покажчика базового типу * /
triangle t; / * Створення об'єктів породжених типів * /
square s;
р = t;
p-> set_dim (10.0, 5.0);
p-> show_area ();
p = s;
p-> set_dim (10.0, 5.0);
p-> show_area ();
return 0;
>

class circle: public figure public:
void show_area () cout <<"Circle with radius ";
cout < cout <<"has an area of ";
cout <<3.14 * x * x;
>
>;

Перш ніж використовувати клас circle, подивимося уважно на визначення функції show_area (). Звернемо увагу, що вона використовує тільки величину х, яка виражає заради-ус. Як відомо, площа круга обчислюється за формулою π R 2. Однак функція set_dim (), визна-поділена в класі figure, вимагає не одного, а двох аргументів. Оскільки клас circle не злидні-ється в другій величиною, то як же нам бути в даній ситуації?

Є два шляхи для вирішення цієї проблеми. Перший полягає в тому, щоб викликати set_dim (), використовуючи в якості другого параметра фіктивний параметр, який не буде ис-користування мож. Недоліком такого підходу є необхідність запам'ятати цей винятковий випадок, що по суті порушує принцип «один інтерфейс - безліч методів».

Краще рішення даної проблеми пов'язано з використанням параметра у в set_dim () зі зна-ням за замовчуванням. У такому випадку при виклику set_dim () для кола необхідно вказати тільки радіус. При виклику set_dim () для трикутника або прямокутника вкажемо обидві величини. Нижче показана програма, яка реалізує цей підхід:

#include
class figure protected:
double x, y;
public:
void set_dim (double i, double j = 0) x = i;
y = j;
>
virtual void show_area () cout <<"No area computation defined ";
cout <<"for this class .\n";
>
>;
class triangle: public figure public:
void show_area () cout <<"Triangle with height ";
cout < cout <<" has an area of ";
cout <>
>;
class square: public figure public:
void show_area () cout <<"Square with dimensions ";
cout < cout <<" has an area of ";
cout <>
>;
class circle: public figure public:
void show_area () cout <<"Circle with radius ";
cout < cout < cout <<3.14 * x * x;
>
>;
int main ()
figure * p; / * Створення покажчика базового типу * /
triangle t; / * Створення об'єктів породжених типів * /
square s;
circle с;
р = t;
p-> set_dim (10.0, 5.0);
p-> show_area ();
p = s;
p-> set_dim (10.0, 5.0);
p-> show_area ();
p = c;
p-> set_dim (9. 0);
p-> show_area ();
return 0;
>

Цей приклад також показує, що при визначенні базового класу важливо проявляти максималь-но можливу гнучкість. Не слід накладати на програму якісь непотрібні обмеження.

Схожі статті