|
|||||||
Время создания: 20.08.2021 11:37
Текстовые метки: c++, c++11, модификатор, override, final
Раздел: Компьютер - Программирование - Язык C++ (Си++)
Запись: xintrea/mytetra_syncro/master/base/1629448631tneki83k8s/text.html на raw.github.com
|
|||||||
|
|||||||
Модификатор override Модификатор override появился в стандарте C++11 и используется при описании методов дочернего класса. Модификатор override следует писать для тех методов, которые по задумке программиста являются переопределенными методами базового класса. Данный модификатор пишется после имени метода. В заголовочном файле описание метода с использованием override выглядит так: class B : public A { public: virtual const char* getVersion() override; }; В реализации (т. е. в *.cpp-файле), модификатор override не пишется. Модификатор override позволяет компилятору следить за тем, чтобы метод, помеченный этим модификатором действительно переопределял метод базового класса. В языке C++ метод дочернего класса будет переопределять метод базового класса только в том случае, если его сигнатура полностью совпадает с сигнатурой базового класса (одно исключение из этого правила есть, оно написано ниже). В больших проектах, или просто по запарке, можно не обратить внимание, например, на то, что в одной сигнатуре используется обычный указатель, а в другой константный указатель. И программист будет думать что он переопределил метод, а на самом деле переопределения не произошло. Чтобы избежать таких ошибок, рекомендуется для каждого метода, который переопределяет базовый метод, писать модификатор override. Модификатор override и ковариантный тип возврата Есть один случай, когда тип возврата переопределения может не совпадать с типом возврата виртуального метода родительского класса, но при этом оставаться переопределением: Если базовый виртуальный метод возвращает указатель или ссылку на класс, то переопределенные методы могут возвращать указатель или ссылку на свой собственный класс. Другими словами, в переопределенных методах в качестве возвращаемого типа можно вместо указателя на родительский класс возвращать указатель на дочерний класс. Это называется ковариантным типом возврата. Например: #include <iostream>
class Parent { public: // Этот метод getThis() возвращает указатель на класс Parent virtual Parent* getThis() { std::cout << "called Parent::getThis()\n"; return this; } void printType() { std::cout << "returned a Parent\n"; } };
class Child : public Parent { public: // Обычно, типы возврата переопределений и виртуальных функций родительского класса должны совпадать. // Однако, поскольку Child наследует класс Parent, следующий метод может возвращать Child* вместо Parent* virtual Child* getThis() { std::cout << "called Child::getThis()\n"; return this; } void printType() { std::cout << "returned a Child\n"; } };
int main() { Child ch; Parent *p = &ch; ch.getThis()->printType(); // вызывается Child::getThis(), возвращается Child*, вызывается Child::printType p->getThis()->printType(); // вызывается Child::getThis(), возвращается Parent*, вызывается Parent::printType } Результат выполнения программы: called Child::getThis() Внимание! Некоторые старые компиляторы могут не поддерживать ковариантные типы возврата. В примере, приведенном выше, сначала вызывается ch.getThis(). Поскольку ch является объектом класса Child, то вызывается Child::getThis(), который возвращает Child*. Этот Child* затем используется для вызова невиртуальной функции Child::printType(). Затем выполняется p->getThis(). Переменная p является указателем класса Parent на объект ch класса Child. Parent::getThis() — это виртуальная функция, поэтому вызывается переопределение Child::getThis(). Хотя Child::getThis() и возвращает Child*, но, поскольку родительская часть объекта возвращает Parent*, возвращаемый Child* преобразовывается в Parent*. И, таким образом, вызывается Parent::printType(). Тип Child* в данном примере будет возвращен только в том случае, если будем вызывать метод getThis() с объектом класса Child. Модификатор final Модификатор final используется для двух случаев:
Если пользователь пытается переопределить метод или наследовать класс с модификатором final, то компилятор выдаст ошибку. Модификатор final, так же как модификатор override, пишется после имени метода или имени класса. Описание неизменяемого метода: virtual const char* getVersion() override final; Описание неизменяемого класса: class B final : public A { public: virtual const char* getVersion() override; }; При сборке программы компилятор проверяет, не происходит ли попытки переопределить "финализированный" метод или класс, и если находит, то генерирует ошибку времени компиляции. |
|||||||
Так же в этом разделе:
|
|||||||
![]() |
|||||||
|
|||||||
|