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.

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