Derived classes still have a default assignment operator

If a class does not declare an explicit assignment operator (operator=()), a default operator will be created by the C++ compiler which will copy over each of the data members of the class. A class can (and often they do) override this behaviour by declaring the assignment operator. If a class derives from a base class with a non-default assignment operator, but does not have an assignment operator itself, the C++ compiler will still create a default operator which copies the members of the derived (but not the base) class.

This above may seem like an obvious statement to experienced C++ users, but a recent question came up which showed to me that less experienced people can be tripped up by this issue, so here is a quick review of the above.

A class without an assignment operator, e.g.,

struct A {
  int x;
};

will have a default assignment operator defined by the compiler that is functionally similar to:

struct A {
  int x;

  // Equivalent to the default assignment operator
  A& operator= (const A& a)
  {
    x=a.x;
    return *this;
  }
};

Declaring a assignment operator overrides this behaviour, e.g.,

struct A {
  int x;

  A& operator= (const A& a)
  {
    // do nothing
    return *this;
  }
};

in this case the operator does not copy the members of the class.

If a class is derived from such a class with non-default operator, but itself does not declare this operator, e.g.,

struct B:
  public A {

  int y;

};

then a default operator will created by the C++ compiler that will copy over the members of the derived class only. In the above case this means y will be copied on assignment while x will not be copied.

Here is the complete program illustrating this:

// Bojan Nikolic <bojan@bnikolic.co.uk>

#include <iostream>

struct A {
  int x;

  A& operator= (const A& a)
  {
    // do nothing
    return *this;
  }
};

struct B:
  public A {

  int y;

};

int main(void)
{
  B b1;
  b1.x=3;
  b1.y=4;

  B b2;
  b2.x=b2.y=0;
  b2=b1;

  std::cout<<"x: "<<b2.x<<std::endl
        <<"y: "<<b2.y<<std::endl;

  // The output is:
  // x: 0
  // y: 4
  //

}