28. C++ Виртуальные методы класса, ключевые слова virtual и override

Виртуальные методы класса, ключевые слова 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; //выводим данные на экран
    }

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *