Geod24
Geod24

Reputation: 893

Base operator called instead of Derived one - Normal behaviour?

As I'm currently playing with C++, I come up to an issue. Code below:

#include        <iostream>

class Base {
public:
  virtual ~Base()                   {}


  virtual Base&         operator=(const Base& o)
  {
    std::cout << "Base operator called" << std::endl;
    return *this;
  }
};

class Derived : public Base {
public:
  virtual ~Derived() {}

  virtual Base&         operator=(const Base& o)

  {
    std::cout << "Derived operator called" << std::endl;
    return *this;
  }
};

int     main(void)
{
  Derived       a;
  Derived       b;
  Base&         c = a;
  Base&         d = b;

  a = b;                        // Base called                                                                                                                                 
  a = static_cast<Base>(b);     // Derived called                                                                                                                              
  a = d;                        // Derived called                                                                                                                              
  c = d;                        // Derived called                                                                                                                              
  return (0);
}

The comment show what output I get. The last 3 results are very much predictable, but I can't understand the first.

As shown in the second one (static_cast), Derived::operator= is called when the right operand is a Base class. However, g++ (4.5.3-r2, gentoo Linux) success to understand that it must use the 'Base' class, but doesn't go down the inheritance tree.

So I was expecting either Derived::operator= to be called, or g++ complaining for no "Derived& Derived::operator=(const Derived&)". Could someone explain this behaviour to me ? Thanks!

Upvotes: 4

Views: 128

Answers (1)

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361402

There is a compiler generated copy-assignment, i.e operator=(Derived &) in Derived class, because Derived::operator=(Base const&) is not copy-assignment for Derived. This does not prevent compiler from generating the copy-assignment if you use assignment in your code.

So this line:

 a = b;  // Base called     

calls the compiler generated operator=(Derived &) for Derived class, which then calls the operator=(Base const&). Hence Base called is printed.

Experiment: add this to Derived class:

Derived & operator=(Derived const & obj) : Base(obj)
{
   std::cout << "copy-assignment called" << std::endl;
   return *this;
}

Now, a=b will cause to print this:

Base called
copy-assignment called   

Note the order of printing also.

Hope that clarify your doubt.


Now this,

a = static_cast<Base>(b);  /// Derived called    

is functionally equivalent to this:

Base ___generated_tmp = static_cast<Base>(b);
a = ___generated_tmp;

means, a = ___generated_tmp calls operator=(Base const&), as the type of ___generated_tmp is Base.

And the rest two are pretty much clear, as you already seem to know.

Upvotes: 3

Related Questions