AUTOSAR C++14 Rule 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.

The 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