30

There is this code:

#include <iostream>

class Base {
public:
    Base(){
        std::cout << "Constructor base" << std::endl;
    }
    ~Base(){
        std::cout << "Destructor base" << std::endl;
    }
    Base& operator=(const Base& a){
        std::cout << "Assignment base" << std::endl;
    }
};

class Derived : public Base{
public:

};

int main ( int argc, char **argv ) {
    Derived p;
    Derived p2;
    p2 = p;
    return 0;
}

The output after compilation by g++ 4.6:

Constructor base
Constructor base
Assignment base
Destructor base
Destructor base

Why assignment operator of base class is called altough it is said that assignment operator is not inherited?

scdmb
  • 15,091
  • 21
  • 85
  • 128
  • 1
    possible duplicate of [Trouble with inheritance of operator= in C++](http://stackoverflow.com/questions/3882186/trouble-with-inheritance-of-operator-in-c) – Bo Persson Feb 06 '12 at 14:29

6 Answers6

49

Actually, what is called is the implicitly defined operator = for Derived. The definition provided by the compiler in turn calls operator = for the Base and you see the corresponding output. The same is with the constructor and destructor. When you leave it to the compiler to define operator =, it defines it as follows:

Derived& operator = (const Derived& rhs)
{
    Base1::operator =(rhs);
    ...
    Basen::operator =(rhs);
    member1 = rhs.member1;
    ...
    membern = rhs.membern; 
}

where Base1,...,Basen are the bases of the class (in order of specifying them in the inheritance list) and member1, ..., membern are the members of Derived (not counting the members that were inherited) in the order you declared them in the class definition.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • It would be good to add a `return` statement to that definition, probably it just does `return *this`? Which might be different to the behavior of `Base1` if `Base1`'s operator does not return a reference to itself (which is *normally* the case though). – Johannes Jun 26 '20 at 22:08
41

You can also use "using":

class Derived : public Base{
public:
    using Base::operator=;
};

http://en.cppreference.com/w/cpp/language/using_declaration

I read this post several time before someone helped me with this.

Paul Thomas
  • 511
  • 4
  • 3
  • 3
    Finally, someone said it. +1. See also: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – underscore_d Sep 08 '16 at 21:59
  • 1
    What happens if you declare additional variables in the Derived class, but use this technique? Will it properly assign the new variables from Derived? – ZeroZ30o Feb 12 '23 at 23:23
25

You don't have a default

Derived& operator=(const Base& a);

in your Derived class.

A default assignment operator, however, is created:

Derived& operator=(const Derived& a);

and this calls the assignment operator from Base. So it's not a matter of inheriting the assignment operator, but calling it via the default generated operator in your derived class.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 11
    operator= is inherit from based class as I quote from 98 c++ standard "Operator functions are inherited in the same manner as other base class functions." It has just been hidden by implicitly created operator= for Derived class. – RoundPi Feb 06 '12 at 15:12
  • 2
    "It has just been hidden by implicitly created operator= for Derived class". Just like if base class has void func(int) and derived class has void func(double), base class function void func(int) is hidden. On similar lines base class operator= is hidden by derived class operator=. – Sandeep Apr 19 '15 at 23:07
  • 1
    ...and to be clear, since the base `operator=` has only been hidden, it can be unhidden in the derived class with `using Base::operator=;` and boom: there it is, inherited. See: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – underscore_d Sep 08 '16 at 22:01
  • @Luchian: if it is not inherited make it private in base class and see the result – Raindrop7 Nov 14 '16 at 20:28
11

Standard says (12.8):

An assignment operator shall be implemented by a non-static member function with exactly one parameter. Because a copy assignment operator operator= is implicitly declared for a class if not declared by the user (12.8), a base class assignment operator is always hidden by the copy assignment operator of the derived class.

and then assignment operator of derived call your base

The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy-/move assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared in the class definition.

Yola
  • 18,496
  • 11
  • 65
  • 106
-1

That is because the default assignment operator created calls it's base assignment operator, i.e. it isn't inherited but still called as part of the default assignment operator.

Cpt. Red
  • 102
  • 3
  • The assignment operator **is** inherited from the base. It's just hidden by the compiler-generated one in the derived class. Using `using Base::operator=;` would prove this by unhiding the base implementation and making it available via the derived class. See: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – underscore_d Sep 08 '16 at 21:58
-1

Assignment operator is indeed not inherited. Inheriting that operator would enable you to assign a Base to a Derived, however Base b; p = a; will (rightfully) fail to compile.

What happens is that the compiler generates an operator=, since you haven't defined a custom one for Derived. The autogenerated operator= will call the assignment operators of all all base classes and all members. In that aspect it is much the same as constructors/destructors, which also call the respective function on all Bases/members.

Grizzly
  • 19,595
  • 4
  • 60
  • 78
  • 1
    The assignment operator **is** inherited from the base. It's just hidden by the compiler-generated one in the derived class. Using `using Base::operator=;` would prove this by unhiding the base implementation and making it available via the derived class. See: http://stackoverflow.com/questions/4122214/why-operator-doesnt-get-inherited-from-a-template-class – underscore_d Sep 08 '16 at 21:58