Assignment operator not available in derived class

c++ assignment operator overloading derived class
assignment operator inheritance c++
c++ operator< inheritance
c++ inherit conversion operator
candidate function the implicit copy assignment operator not viable no known conversion from
assignment operator c++ overload
call base class assignment operator
c++ call base class overloaded operator

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?

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.

C++ assignment operator in derived class, 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  This statement calls the operator= of class X, which is not virtual. It assigns the members of class X if it has any, but it won’t assign the members of the derived classes. What’s a C++ programmer to do? We’re going to see several solutions. I’ll tell you right away, none of them is ideal, they have advantages and drawbacks.

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.

20.3 Assignment operator in derived classes, It is not always trivial to define (overload) properly the assignment operator in a derived class. It may happen that there is a non-private assignment operator  Assignment operator in derived classes. It is not always trivial to define (overload) properly the assignment operator in a derived class. It may happen that there is a non-private assignment operator defined in base class. If a derived class does not overload the assignment operator, then the version from the base class will be used to perform the assignment of the inherited subobject; however, default assignment (field-by-field) will be used to assign non-inherited members (what can be not

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.

Is assignment operator inherited?, In C++, like other functions, assignement operator function is inherited in derived class. For example, in the following program, base class assignment operator  Is assignment operator inherited? In C++, like other functions, assignement operator function is inherited in derived class. For example, in the following program, base class assignment operator function can be accessed using the derived class object.

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=;
};

Assignment Operators, C++ FAQ, If you do not declare a copy assignment operator for a class A , the compiler will of a derived class hides the copy assignment operator of its base class. The assignment operator has some additional restrictions. It can be overloaded only as a nonstatic member function, not as a friend function. It is the only operator that cannot be inherited; a derived class cannot use a base class's assignment operator.

Copy assignment operators (C++ only), A move assignment operator of class T is a non-template non-static member If some user-defined move assignment operators are present, the user or virtual base without a move assignment operator that is not trivially  Default assignment operator. Unlike other operators, the compiler will provide a default public assignment operator for your class if you do not provide one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).

Move assignment operator, If TFoo::operator= is not virtual, this assignment will slice the object. So shouldn't There is also an issue with implementing derived class assignment. Usually  Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.

When to use virtual assignment, In the C++ programming language, the assignment operator, = , is the operator used for class My_Array{ int* array; int count; public: My_Array& operator=(​const swap all the members (and base subobject, if applicable) with other using objects, which could leave descendant's fields uninitialized, is not permitted. If you define your own assignment operators, the compiler will not automatically call your base class’s assignment operators for you. Unless your base class’s assignment operators themselves are broken, you should call them explicitly from your derived class’s assignment operators (again, assuming you create them in the first place).

Comments
  • I actually had to read Mark's answer to make sense of your second paragraph, but once I understood that your answer is very informative.
  • It does not behave differently, the same issue will arise with any other method.
  • @spectras "same issue" ?? usually mehtods are inherited by derived classes and can be used without further measures. Any other method will not be implicitly declared by the compiler
  • @user463035818 the issue here is name hiding. See Some programmer dude's answer. You'll encounter this issue anytime a method in derived class has the same name as methods in base class ^^
  • @spectras ok, thanks, now I understand what you mean, though OP didnt declare a operator= in the derived and it is special with regard to hiding
  • The best answer, imo, since it addresses why hiding the assignment operator is desirable, and the caveats with dragging it in.
  • Isn't this only true because of the implicitly declared copy assignment in B hiding A::operator=?
  • @spectras Yes that's true, which is why I updated the answer (just when you posted the comment).