Is the base statement called instead of Derived one normal behavior?

As I am playing with C ++ right now, I approach the problem. 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 shows what result I get. The last 3 results are very predictable, but I do not understand the first.

As shown in the second (static_cast), Derived :: operator = is called when the right operand is a base class. However, g ++ (4.5.3-r2, gentoo Linux) manages to understand that it should use the "Base" class, but does not go down the inheritance tree.

So, I was expecting a call to Derived :: operator = or g ++ complaining about the lack of "Derived & Derived :: operator = (const Derived &)". Can someone explain this behavior to me? Thanks!

+4
source share
1 answer

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

So this line:

  a = b; // Base called 

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

Experiment: add this to the Derived class:

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

Now a=b will print:

The base is called
copy assignment is called

Also pay attention to the printing order.

Hope to clarify your doubts.


Now this,

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

functionally equivalent to this:

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

means a = ___generated_tmp calls operator=(Base const&) , since the type ___generated_tmp is equal to Base .

And the other two are pretty clear, as you already know.

+3
source

All Articles