Добавил:
Developer Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Магистратура Языки программирования С,C++ / Доклад на тему №8 Наследование, перегрузка, переопределение.docx
Скачиваний:
1
Добавлен:
17.03.2024
Размер:
1.31 Mб
Скачать

6 Виртуальные методы и таблица виртуальных методов

Одним из важнейших приёмов реализации полиморфизма являются виртуальные методы. Они позволяют создавать общий код, который может работать как с объектами базового класса, так и с объектами любого его класса-наследника.

Виртуальный метод (виртуальная функция) — это метод класса, который может быть переопределён в классах-наследниках так, что конкретная реализация метода для вызова будет определяться во время исполнения.

Представим следующую задачу:

Необходимо создать класс «Пистолет». У данного класса реализован метод «Выстрелить», который включает в себя отображение одного выстрела.

От данного класса есть наследуемый класс «Пистолет – пулемет», который будет иметь тот же метод, что и родительский класс, но включать в себя отображение нескольких выстрелов.

Листинг № 6.1 – Программный код

#include <iostream>

class Gun /*Класс «Пистолет» с методом «Выстрелить»*/

{

public:

void Shoot(){

std::cout << "BANG!\n";

}

};

class Gun_pul : public Gun /*Класс «Пистолет – пулемет» с методом «Выстрелить»*/

{

public:

void Shoot(){

std::cout << "BANG! BANG! BANG!\n";

}

};

int main()

{

setlocale(LC_ALL, "ru");

//Gun gun;

//gun.Shoot();

//Gun_pul gun_pul;

//gun_pul.Shoot();

Gun* pb = new Gun_pul;

pb->Shoot();

return 0;

}

В данном случае решение о том, какую функцию звать — Gun::Shoot или Gun_pul:: Shoot — принимается на основе известного компилятору типа указателя, т.е. Gun::Shoot.

Рисунок 6.1 – Результат выполнения программы

Однако, хотелось бы иметь возможность объявить наследника так, чтобы у объектов типа-наследника всегда звалась новая, определенная в типе-наследнике функция, независимо от того, какая функция определена в базовом классе.

Такое требует специальной поддержки во время выполнения, ибо компилятор, увидев Gun*, не знает, есть ли это объект, созданный как Gun, или же Gun – часть в объекте класса Gun_pul.

Для этого необходимо использовать виртуальные методы, которые объявляются с помощью оператора virtual, определяющийся в вершине дерева наследования, где он встречается впервые. Писать virtual в потомках уже не обязательно.

Листинг № 6.2 – Программный код

#include <iostream>

class Gun /*Класс Пистолет с методом "Выстрелить"*/

{

public:

virtual void Shoot()

{

std::cout << "BANG!\n";

}

};

class Gun_pul : public Gun /*Класс Пистолет- пулемет с методом "Выстрелить"*/

{

public:

void Shoot()

{

std::cout << "BANG! BANG! BANG!\n";

}

};

int main()

{

setlocale(LC_ALL, "ru");

Gun* pb = new Gun_pul;

pb->Shoot();

return 0;

}

Рисунок 6.2 – Результат выполнения программы