Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ assignment operator in derived class [duplicate]

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?

like image 843
Max Avatar asked Jun 24 '15 14:06

Max


1 Answers

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;
}
like image 55
Barry Avatar answered Nov 02 '22 08:11

Barry