В програмі 13.1 ми розглянемо, що буває, коли базовий і похідний класи містять функції з тим самим іменем і до них звертаються за допомогою вказівників, але без використання віртуальних функцій.
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<bios.h>
//////////
class Base
{public:
void show()
{cout<<”Base\n”;}
};
////////////
class Derv1:public Base
{public:
void show()
{cout<<”Derv1\n”;}
};
/////////////
class Derv2:public Base
{public:
void show()
{cout<<”Derv2\n”;}
};
//////////////
int main()
{clrscr();
Derv1 dv1;
Derv2 dv2;
Base* ptr;
ptr=&dv1;
ptr->show();
ptr=&dv2;
ptr->show();
bioskey(0);
return 0;
}
Програма 13.1
Класи Derv1 і Derv2 є спадкоємцями класу Base. В кожному з цих класів є свій метод show(). В головній функції ми створюємо об’єкти обох похідних класів, а також вказівник на об’єкт базового класу. Потім адресу об’єкту породженого класу ми заносимо у вказівник базового класу Як ми вже знаємо з вивчення Паскалю, вказівники на об’єкти породжених класів можна присвоїти змінним-вказівникам на об’єкти базових класів (але не навпаки).
Спробуємо розібратися, яка саме функція виконується в рядку
ptr->show();
функція базового чи похідного класу, тобто Base::show() чи Derv::show()? Виконавши програму, ми одержимо такий результат:
Base
Base
Отже, в обох випадках виконався метод базового класу. Компілятор не звертає уваги на вміст вказівника ptr, а вибирає той метод, який задовольняє тип вказівника.
Доступ до віртуальних методів через вказівники
Дещо змінимо програму: поставимо ключове слово virtual перед оголошенням функції show() в базовому класі.
Далі приведений лістінг програми 13.2.
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<bios.h>
//////////
class Base
{public:
Virtual void show()
{cout<<”Base\n”;}
};
////////////
class Derv1:public Base
{public:
void show()
{cout<<”Derv1\n”;}
};
/////////////
class Derv2:public Base
{public:
void show()
{cout<<”Derv2\n”;}
};
//////////////
int main()
{clrscr();
Derv1 dv1;
Derv2 dv2;
Base* ptr;
ptr=&dv1;
ptr->show();
ptr=&dv2;
ptr->show();
bioskey(0);
return 0;
}
Програма 13.2
Виконавши програму, одержимо:
Derv1
Derv2
тобто, виконуються методи похідних класів, а не базового. Ми поміняли вміст ptr з адреси з класу Derv1 на адресу з класу Derv2 і помінялося реальне виконання show(). Отже, той сам виклик
ptr->show()
ставить на виконання різні функції залежно від вмісту ptr. Компілятор вибирає функцію, яка задовольняє тому, що записано у вказівнику, а не його типу.