C++ assignment operator in derived class

12,255

Solution 1

If you don't declare a copy assignment operator, the compiler will declare one for you. So your class B really looks like:

class B : public A {
public:
    // explicit
    B();
    virtual ~B();
    virtual void doneit();

    // implicit
    B(const B&);
    B& operator=(const B&);
};

The implicit copy assignment operator hides the A::operator=(double) that you wrote, so it's the only candidate that name lookup will find. Of course, it's not a viable candidate, since double isn't convertible to B, hence the error.

To use the A::operator=(double ) operator, you have to explicitly bring it into scope:

using A::operator=;

But then you're not going to be assigning any of the B part. So it'd be better to be more explicit:

B& operator=(double g) {
    // B stuff here

    // A stuff
    A::operator=(g);

    return *this;
}

Solution 2

The copy assignment operator of the derived class that is implicitly declared by the compiler hides assignment operators of the base class. Use using declaration in the derived class the following way

class B: public A{
protected:
public:
  using A::operator =;     
  B():A(){};
  virtual ~B(){};
  virtual void doneit(){myWrite();}
};

Another approach is to redeclare the virtual assignment operator in the derived class

B & operator=(double g) { A::operator =( g ) ;return *this;}

In this case you can use the polymorphism. For example

#include <iostream>

class A
{
public:
  double x,y;
  A(): x{0}, y{0} {}
  virtual A & operator =( double g ){ x = g; y = g; return *this; }
  virtual ~A(){}
};


class B: public A
{
public:
  B() : A(){}
  virtual B & operator =( double g ) override { A::operator =( 2 * g ) ; return *this; }
  virtual ~B(){}
};

int main() 
{
    A a;
    B b;

    A *p = &a;

    *p = 10;

    std::cout << p->x << ' ' << p->y << std::endl; 

    p = &b;

    *p = 10;

    std::cout << p->x << ' ' << p->y << std::endl; 

    return 0;
}  

The program output is

10 10
20 20
Share:
12,255
Max
Author by

Max

I am a scientist working on molecular simulations. My technical interests are in parallel and high performance computing. I use routinely C, C++, python. And to help friends (:-) I have also some interests in javascript/GAS.

Updated on June 04, 2022

Comments

  • Max
    Max almost 2 years

    I don't quite understand why for an assignment a derived class do not call the corresponding operator of the base class, if its own does not exist. Look at the code:

    #include <iostream>
    using namespace std;
    
    class A{
    protected:
      void myWrite(){
        cout << " Base " <<endl;
      }
    public:
      double x,y;
      A(): x{0},y{0}{};
      virtual A & operator=(double g){x=g;y=g;return *this;}
      virtual ~A(){};
      virtual void doneit(){myWrite();}
    };
    
    
    class B: public A{
    protected:
    public:
      B():A(){};
      virtual ~B(){};
      virtual void doneit(){myWrite();}
    };
    
    int main() {
      A jj;
      B pp;
    
      pp=0.0;
      return 0;
    }
    

    As it is the code does not compile. Of course if I define an "operator=" for B identical to that for A, everything works, but why the B "operator=" is not called by default if the one in the derived class is not defined?? Could you help shed some light on this issue?

    The gcc compiler says ../src/tito.cpp:40:4: error: no viable overloaded '=' pp=0.0; ~~^~~~ ../src/tito.cpp:28:7: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'double' to 'const B' for 1st argument class B: public A{ ^ 1 error generated.

    Could you explain why it doesn't work?

  • StenSoft
    StenSoft almost 9 years
    Yes, the main rationale is that parent's operator = does not assign the child's part so implicitly using it can easilly create broken objects.
  • Max
    Max almost 9 years
    Thank you for the very useful comment!!
  • jaques-sam
    jaques-sam over 5 years
    I would add the assignment of the B stuff after the A stuff, so that the self-check, which is done when implementing B& operator=(double A), is done at the beginning for both operator= functions (as the self-check should be done only at the base class).
  • Barry
    Barry over 5 years
    @DrumM What self-check? We're assigning from a double.