exponenta event banner

Правило AUTOSAR C++ 14 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