AUTOSAR C++14 Rule A10-3-1

Объявление виртуальной функции должно содержать точно один из этих трех спецификаторов: (1) виртуальный, (2) замените, (3) финал

Описание

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

Объявление виртуальной функции должно содержать точно один из этих трех спецификаторов: (1) виртуальный, (2) замените, (3) финал.

Объяснение

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

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

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

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

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

  • Только virtual объявить новую виртуальную функцию.

  • Только override объявить неитоговую переопределяющую функцию виртуальной функции.

  • Только final объявить итоговую переопределяющую функцию виртуальной функции.

Реализация Polyspace

Polyspace® отмечает объявление виртуальных функций если:

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

  • Объявление использует больше чем один из спецификаторов.

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

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

Примеры

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

#include<cstdint>
class Base
{
public:
	virtual void F() noexcept = 0;                 // Compliant
	virtual void G() noexcept final = 0;           // Noncompliant
	virtual void H() noexcept final {}             // Noncompliant
	virtual void J() noexcept {}                   // Compliant
	virtual void K() noexcept {}                   // Compliant
	virtual ~Base() {}                             // Compliant
	virtual void M() noexcept {}                   // Compliant
	virtual void Z() noexcept {}                   // Compliant
	virtual void X() throw() {}                    // Compliant
	virtual void Y() noexcept {}                   // Compliant
};                                                 

class Derived : public Base                        
{                                                  
public:                                          
	~Derived() {}                                  // Noncompliant
	virtual void F() noexcept override {}          // Noncompliant
	void K() noexcept override final {}            // Noncompliant
	virtual void M() noexcept {}                   // Compliant
	void Z() noexcept override {}                  // Compliant
	void J() noexcept {}                           // Noncompliant
	void J(int) noexcept {}                        // Compliant
	virtual void X() throw() final {}              // Noncompliant
	virtual void Y() noexcept override final {}    // Noncompliant
};
class DD: public Derived{
//	void J(int) noexcept override{}       //Compilation error
};
main(){
	//...
}

  • Деструктор производного класса ~Derived() виртуальная функция. Его объявление нарушает это правило, потому что объявление не содержит ни один из этих трех спецификаторов для виртуальных функций.

  • Объявление чистой виртуальной функции Base::G() также нарушает это правило, потому что объявление содержит оба virtual и final как спецификаторы. Чистая виртуальная функция, которая также задана как final избыточно.

  • Объявление виртуальной функции Derived::J() нарушает это правило потому что Derived::J() неявно заменяет виртуальную функцию Base::J() не используя спецификатор override.

  • Объявления виртуальных функций Derived::X() и Derived::Y() нарушьте это правило, потому что их объявления используют больше чем один спецификатор.

Объявление функционального DD::J(int) производит ошибку компиляции потому что DD::J(int) попытка состоит в том, чтобы заменить Derived::J(int). Поскольку Derived::J(int) имеет различную подпись, чем Base::J(), возможно, ошибкой, Derived::J(int) больше не виртуальная функция. Попытка заменить Derived::J(int) DD::J(int) результаты в ошибке компиляции. Используя точно один спецификатор в объявлении виртуальных функций может помочь обнаружить ошибки.

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

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