exponenta event banner

Правило AUTOSAR C++ 14 A10-3-5

Определяемый пользователем оператор назначения не должен быть виртуальным

Описание

Определение правила

Определяемый пользователем оператор назначения не должен быть виртуальным.

Объяснение

Определение оператора назначения как virtual в базовом классе указывает, что его необходимо переопределить в производных классах. Переопределение оператора назначения в производных классах может привести к неопределенному поведению и ошибкам времени выполнения. Рассмотрим этот фрагмент кода, в котором оператор виртуального назначения переопределяется в двух производных классах.

class Base {public:
	virtual Base& operator=(Base const& oth) = 0;
	//...
};
class Derived public: Base{ public:
	Derived& operator=(Base const& oth) override{/*...*/}
	//...
};
class Derived2 public: Base{public:
	Derived2& operator=(Base const& oth) override{/*...*/}
	//...
};
main(){
	Derived d1; 
       Derived2 d2;
	d1 = d2;
}
Поскольку Derived::operator= и Derived2::operator= отвергает Base::operator=, их списки параметров должны быть идентичными.

  • Derived::operator= принимает ссылку на Base объект в качестве входных данных и возвращает ссылку на Derived.

  • Derived2::operator= принимает ссылку на Base объект в качестве входных данных и возвращает ссылку на Derived2.

Derived::operator= принимает ссылки на оба Base и Derived , поскольку ссылки на производные классы совместимы с их базовыми классами. Аналогично, Derived2::operator= также принимает ссылки на оба Base и Derived2 объектов класса. Назначение Derived объект в Derived2 объект в d1=d2 не приводит к ошибке компиляции. Объекты d1 и d2 не связаны между собой. Операции назначения, копирования или перемещения между такими несвязанными объектами не определены и могут привести к ошибкам во время выполнения.

Во избежание неопределенного поведения и ошибок во время выполнения следует сохранять определяемые пользователем операторы назначения невиртуальными. Это правило применяется к следующим операторам:

  • Назначение

  • Копирование и перемещение назначения

  • Все составные назначения

Внедрение Polyspace

Polyspace ® помечает объявление любых виртуальных операторов назначения в базовом классе.

Поиск неисправностей

Если вы ожидаете нарушения правила, но не видите его, обратитесь к разделу Нарушения стандартов кодирования не отображаются.

Примеры

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

В этом примере показано, как флаги Polyspace virtual операторы назначения.

#include <cstdint>
class Base
{
  public:
    virtual Base& operator=(Base const& oth) = 0;   // Noncompliant
    virtual Base& operator+=(Base const& rhs) = 0; // Noncompliant
};
class Derived : public Base
{
  public:
    Derived& operator=(Base const& oth) override 
    {
      return *this;
    }
    Derived& operator+=(Base const& oth) override 
    {
      return *this;
    }
    Derived& operator-=(Derived const& oth) // Compliant
    {
      return *this;
    }
};
class Derived2 : public Base
{
  public:

    Derived2& operator=(Base const& oth) override    
    {
      return *this;
    }
    Derived2& operator+=(Base const& oth) override    
    {
      return *this;
    }
    Derived2& operator-=(Derived2 const& oth)   // Compliant
    {
      return *this;
    }
};
/*
*/
void Fn() noexcept
{
  Derived b;
  Derived2 c;
  b = c;  
  b += c; 
  c = b;  
  c += b; 
  // b -= c; // Compilation error
  // c -= b; // Compilation error

}

Классы Derived и Derived2 являются производными от Base. В Base класс, операторы назначения Base::operator= и Base::operator+= объявлены как виртуальные. Ни одна из следующих причин не приводит к ошибкам компиляции:

  • Можно назначить Derived объект b кому Derived2 объект c и наоборот.

  • Вы можете добавить Derived объект b кому Derived2 объект c. Результат можно присвоить либо b или c.

Поскольку b и c являются несвязанными объектами, все предшествующие варианты поведения не определены и могут вызвать ошибки во время выполнения. Объявление Base::operator= и Base::operator+= как virtual в конечном итоге приводят к неопределённому поведению. Polyspace помечает эти операторы виртуального назначения.

Объявление Base::operator-= не является виртуальным. Операции, такие как b-=c и c-=b привести к ошибкам компиляции.

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

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