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

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

    int main(){
        Derived obj1, obj2;
        Base& ba=obj2;
        obj1=ba;//outputs[1]: Derived::operator=( const Base&)

        Derived& de=obj2;
        obj1=de;//outputs[2]: Derived::operator=( const Derived& )

        Base& bb=obj2;
        bb=obj1; //outputs[3]: Derived::operator=( const Base&)
     }

I am confused on the case 3 output, shouldn't assignment operator take the right operand as the function argument, so that obj1 is taken as the argument and since obj1 is class type of Derived, so it will call Derived::operator=( const Derived& )?

For the output[3], why the output is Derived::operator=( const Base& ), not Derived::operator=( const Derived& )?

Xiza Sin
  • 1
  • 1
  • Signatures don't match. – Eljay Jul 04 '21 at 19:39
  • 2
    You are calling `bb.operator=(obj1);` At compile time, name lookup and overload resolution are performed to find a suitable overload; the only candidate is `Base::operator=(const Base&)`. At run-time, the override of that method in the most-derived class is called - that would be `Derived::operator=(const Base&)`. You are looking for double dispatch; C++ doesn't support it directly. – Igor Tandetnik Jul 04 '21 at 19:40
  • 2
    @Igor Maybe worth a formal answer? This is actually a very interesting scenario. – Adrian Mole Jul 04 '21 at 19:44
  • Related question [here](https://stackoverflow.com/questions/969232/why-does-virtual-assignment-behave-differently-than-other-virtual-functions-of-t). – 1201ProgramAlarm Jul 04 '21 at 20:03

1 Answers1

2

The Derived::operator=( const Derived& ) has no override candidate in the Base class. I suggest adding override keyword after each method which is intended to override base class behavior. It costs nothing and can make your code much safer.

If you want to the Derived::operator=( const Derived& ) to be called, you need to provide a correct method signature in the base class:

class Derived; // forward declaration

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

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

class Derived: public Base{
    public:
    virtual Derived& operator=( const Base& ) override {
      std::cout << "Derived::operator=( const Base& )" << std::endl;
      return *this;
    }
    virtual Derived& operator=( const Derived& ) override {
      std::cout << "Derived::operator=( const Derived& )" << std::endl;
      return *this;
    }
};
Tomek Gos
  • 41
  • 3