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