AUTOSAR C++14 Rule A10-3-5

A user-defined assignment operator shall not be virtual

Description

Rule Definition

A user-defined assignment operator shall not be virtual.

Rationale

Defining an assignment operator as virtual in a base class indicates that you want to override it in the derived classes. Overriding the assignment operator in derived classes can lead to undefined behavior and run-time errors. Consider this code snippet where a virtual assignment operator is overridden in two derived classes.

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;
}
Because Derived::operator= and Derived2::operator= overrides Base::operator=, their parameter lists must be identical.

  • Derived::operator= takes reference to a Base object as input and returns a reference to Derived.

  • Derived2::operator= takes reference to a Base object as input and returns a reference to Derived2.

The Derived::operator= accepts references to both Base and Derived class objects because references to derived classes are type-compatible with their base classes. Similarly, the Derived2::operator= also accepts references to both Base and Derived2 class objects. Assigning a Derived object to a Derived2 object in d1=d2 produces no compilation error. The objects d1 and d2 are unrelated. Assigning, copying, or moving operations between such unrelated objects are undefined and can lead to run-time errors.

To avoid undefined behavior and run-time errors, keep user-defined assignment operators as non-virtual. This rule applies to these operators:

  • Assignment

  • Copy and move assignment

  • All compound assignment

Polyspace Implementation

Polyspace® flags the declaration of any virtual assignment operators in a base class.

Troubleshooting

If you expect a rule violation but do not see it, refer to Coding Standard Violations Not Displayed.

Examples

expand all

This example shows how Polyspace flags virtual assignment operators.

#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

}

The classes Derived and Derived2 are derived from Base. In the Base class, the assignment operators Base::operator= and Base::operator+= are declared as virtual. None of the following cause compilation errors:

  • You can assign the Derived object b to Derived2 object c and vice versa.

  • You can add the Derived object b to Derived2 object c. You can assign the result to either b or c.

Because b and c are unrelated objects, all of the preceding behaviors are undefined and can cause run-time errors. Declaring the Base::operator= and Base::operator+= as virtual eventually lead to the undefined behaviors. Polyspace flags these virtual assignment operators.

The declaration of Base::operator-= is non-virtual. Operations such as b-=c and c-=b cause compilation errors.

Check Information

Group: Derived classes
Category: Required, Automated
Introduced in R2020a