Reputation: 544
The assignment operator in base class does not seem to be available in derived class. Given this code:
#include <iostream>
class A{
int value;
public:
A& operator=(int value){
this->value = value;
return *this;
}
};
class B : public A{};
int main(){
B b;
b = 0; // Does not work
return 0;
}
GCC 6.4 says:
error: no match for 'operator=' (operand types are 'B' and 'int')
What is happening?
Upvotes: 31
Views: 2320
Reputation: 38305
As pointed out by the other existing answers, the implicitly generated assignment operator of B
hides the assignment operator defined in A
. This is true for any non-virtual member function in a base class, the only specialty here is the automatically generated assignment operator.
But try to figure out first whether you really want to do this. Imagine your class B
has data members that need to be initialized in some way. How does using the assignment from A
affect these data members? A
doesn't know anything of its derived class data members, they would be left untouched. Have a look at the following scenario where the assignment operator has been made available through a using directive:
class B : public A {
public:
using A::operator=;
int m = 0; // Default-initialize data member to zero
};
B b;
b.m = 42;
b = 0; // Doesn't touch B::m... intended? A bug? Definitely weird.
So yes, it is possible, but error-prone and dangerous, especially when it comes to future modifications of the subclass.
Upvotes: 10
Reputation: 73673
In order to make it work, you need to bring the operator=
into B
's scope:
class B : public A
{
public:
using A::operator=;
};
According to the standard [class.copy.assign/8]:
Because a copy/move assignment operator is implicitly declared for a class if not declared by the user, a base class copy/move assignment operator is always hidden by the corresponding assignment operator of a derived class (16.5.3).
So, because the B::operator=
has been implicitly declared, it has hidden A::operator=
, which requires you to bring it into scope if you want to use it.
Further quote from the standard [over.ass/1]
An assignment operator shall be implemented by a non-static member function with exactly one parameter. Because a copy assignment operator operator= is implicitly declared for a class if not declared by the user (15.8), a base class assignment operator is always hidden by the copy assignment operator of the derived class.
Emphasis is mine.
Upvotes: 20
Reputation: 409374
The problem is that the compiler will add an implicit assignment operator for the B
class, declared as
B& operator=(const B&);
This operator will hide the operator from A
, so the compiler will not know about it.
The solution is to tell the compiler to also use the operator from A
with the using
keyword:
class B : public A
{
public:
using A::operator=;
};
Upvotes: 9
Reputation: 170203
Every class has at least one assignment operator implicitly defined when we don't provide one ourselves.
And when a member function in a derived class is defined with the same name as a member in the base class, it hides all the base class definitions for that name.
You can use a using declaration, but be warned that it will pull all the members named operator=
and allow code like this:
A a;
B b;
b = a;
Which is slightly dubious.
Upvotes: 28