AUTOSAR C++14 Rule A10-3-2

Каждая переопределяющая виртуальная функция должна быть объявлена с переопределением или итоговым спецификатором.

Описание

Управляйте определением

Каждая переопределяющая виртуальная функция должна быть объявлена с переопределением или итоговым спецификатором.

Объяснение

Виртуальные функции реализуют полиморфное поведение в иерархии классов. Если вы объявляете функцию как virtual в базовом классе все экземпляры функции с идентичным списком параметров в производных классах заменяют основную функцию неявно. Если вы используете это неявное действие компилятором для реализации полиморфных функций, это может привести к ошибкам. Например:

  • Функция может стать непреднамеренно virtual потому что его подпись совпадает с виртуальной функцией в базовом классе.

  • Функция может стать непреднамеренно невиртуальной, потому что существуют различия в списке параметров.

Неявно объявляющие переопределяющие виртуальные функции могут также сделать код трудно, чтобы читать.

Чтобы избежать непреднамеренных ошибок и улучшить удобочитаемость, используйте спецификаторы override и final явным образом в каждом объявлении переопределения функций.

Реализация Polyspace

Polyspace® отмечает объявления virtual функции, если все эти операторы верны:

  • Функция находится в производном классе.

  • Подпись функции совпадает с подписью виртуальной функции в базовом классе.

  • Объявление функции испытывает недостаток в спецификаторе override или final.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

#include <cstdint>
class Base
{
public:
	virtual ~Base() {}
	virtual void F() noexcept = 0;
	virtual void G() noexcept {}
	virtual void Z() noexcept {}
	virtual Base& operator+=(Base const& oth) = 0;
};
class Derived1 : public Base
{
public:
	~Derived1() override {}                         //Compliant
	void F() noexcept{}                             //Noncompliant
	virtual void G() noexcept {}                    //Noncompliant
	void Z() noexcept override {}                   // Compliant
	Derived1& operator+=(Base const& oth) override  // Compliant
	{
		return *this;
	}
};
class Derived2 : public Base
{
public:
	~Derived2() {}                                  //  Noncompliant
	void F() noexcept override {}                   //  Compliant
	void G() noexcept override {}                   //  Compliant
	void Z() noexcept override {}                   //  Compliant
	Derived2& operator+=(Base const& oth)           //  Noncompliant
	{                                               
		return *this;                          
	}                                             
};                                                  
class Derived3 : public Base                        
{                                                   
	void F() noexcept override;                     // Compliant 
};

main(){
	
}

  • Объявление функционального Derived::F() отмечается, потому что его подпись совпадает с подписью Base::F() и его объявление не содержит override или final.

  • Объявление функционального Derived::G() отмечается, потому что его подпись совпадает с подписью Base::G() и его объявление не содержит override или final, даже при том, что объявление использует спецификатор virtual.

  • Объявление функционального Derived3::F() в классе Derived3 не отмечается, потому что объявление использует спецификатор override.

Проверяйте информацию

Группа: Производные классы
Категория: необходимый, автоматизированный
Введенный в R2020a