Main Content

AUTOSAR C++14 Rule A10-3-5

A user-defined assignment operator shall not be virtual

Since R2020a

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 Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

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

Version History

Introduced in R2020a