Виртуальные методы класса, ключевые слова virtual и override
В предыдущей теме мы рассмотрели основные принципы наследования, но что делать если мы в классе-наследнике хотим использовать функцию с таким же именем как в базовом классе?
Для этого мы должны «перезаписать функцию» делается это при помощи ключевых слов virtual и override
В базовом классе у перезаписываемой функции пишем что она стала virtual
в классе наследнике создаем функцию с таким же именем, но другой реализацией и добавляем слово override (благодаря слову override компилятор проверяет, что мы не ошиблись при перезаписи с названием и т.д.)
class Person
{
public:
Person()
{
this->Name="Vasya";
this->age= new unsigned int (20); //создание переменной в динамической памяти
}
~Person()
{
delete age; //удаление переменной в динамической памяти
}
virtual void getInfo()
{
cout<<"Name: "<< this->Name <<" age "<< *(this->age) <<endl; //выводим данные на экран } protected: string Name; unsigned int * age; //указатель на переменную в динамической памяти }; class student : public Person { public: student(uint course) { this->course=course;
}
void getInfo() override
{
cout<<"Name: "<< this->Name <<" age "<< *(this->age) <<" studying at "<course<<" course"<<endl; //выводим данные на экран
}
uint course;
};
class student : public Person
{
public:
student(uint course)
{
this->course=course;
}
void getInfo() override
{
cout<<"Name: "<< this->Name <<" age "<< *(this->age) <<" studying at "<course<<" course"<<endl; //выводим данные на экран
}
uint course;
};
В main вызовем:
cout<<"c_Person created"<<endl;
Person c_Person;
c_Person.getInfo();
cout<<endl<<endl;
cout<<"c_Student created"<<endl;
student c_Student(2);
c_Student.getInfo();
Теперь при вызове метода getInfo() у класса Student будет выводится номер курса.
Казалось бы зачем это нужно, но в конце прошлой темы я сказал, что указатель на базовый класс является указателем и на классы наследники:
Что это значит – мы можем создать функцию, принимающую в качестве аргумента базовый класс, а «подсунуть» ему класс наследник.
Продемонстрируем на примере:
Создадим под классами функцию
void PrintInfo(Person *somebody)
{
somebody->getInfo();
}
В main вызовем:
Person c_Person;
student c_Student(2);
PrintInfo(&c_Person);
PrintInfo(&c_Student);
//второй вариант
Person *link=&c_Person;
PrintInfo(link);
link=&c_Student;
PrintInfo(link);
В результате вызовутся методы getInfo классов Person и student соответственно.
Возможность «перезаписи/переопределения» методов в купе с тем, что указатель на базовый класс является указателем и на классы наследники является одним из наиболее удобных механизмов для организации схожих классов с «перегруженными функциями»
Вызов виртуального метода базового класса из класса наследника
Если в классе-наследнике нужно вызвать виртуальный метод базового класса – это можно сделать явно указав принадлежность метода, например в классе student:
void getInfo() override
{
cout<<"Student with ";
::Person:: getInfo(); //вызываем метод getInfo() базового класса
cout<<"studying at "<course<<" course"<<endl; //выводим данные на экран
}