3

It seems to me that Derived class don't inherit base class Assignment operator
if Derived class inherit Base class assignment operator , can you please explain the following example

In the following code I am overriding base class operator= in Derived, so that Derived class default assignment operator calls overloaded operator=

#include <iostream>  
using namespace std;      
class Base  
{  
    public:  
    Base(int lx = 0):x(lx)  
    {  
    }  

    virtual Base& operator=( const Base &rhs)  
    {  
        cout << "calling Assignment operator in Base" << endl;  
        return *this;  
    }

    private:  
    int x;     
};      


class Derived : public Base  
{  
    public:  
    Derived(int lx, int ly): Base(lx),y(ly)  
    {  
    }

    Base& operator=(const Base &rhs)  
    {  
        cout << "Assignment operator in Derived"<< endl;  
        return *this;  
    }  

    private:  
    int y;    
};  



int main()  
{  
    Derived d1(10,20);  
    Derived d2(30,40);  
    d1 = d2;  
}  

It gives the output

calling Assignment operator in Base

I have re-written base class operator= into derived class, so if derived class inherits base class operator= then it should be get overridden by operator= (that i have written in derived class), and now Derived class default operator= should call overridden version and not from the base class operator=.

iammilind
  • 68,093
  • 33
  • 169
  • 336
Amit
  • 84
  • 1
  • 1
  • 4

5 Answers5

5

The compiler generates a default assignment operator for Derived (which hides the operator of Base). However, the default assignment operator calls all assignment operators of the class' members and base classes.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • 1
    can i override Base class operator= in to Derived class? – Amit Jan 17 '12 at 12:02
  • 1
    @Amit: you can't override it. By definition a non-virtual function cannot be overridden, although it can be hidden. Perhaps you want to overload the copy assignment operator in `Derived`. If so, then the correct signature is `Derived& operator=(const Derived &rhs)`. This is the signature that the compiler looks for when you do `d1 = d2`. Since it doesn't find it, it synthesizes the default copy assignment operator instead, and that calls `Base::operator=(const Base &)`. – Steve Jessop Jan 17 '12 at 12:15
  • @Steve: i have changed the code and now my base class opertor= is virtual. – Amit Jan 17 '12 at 12:27
  • 1
    @Amit: that is almost certainly a mistake, virtual assignment operators don't work well. You don't want to allow just any old `Base` object to be assigned to a `Derived` object, because `Base` doesn't provide a value to assign to `y`. – Steve Jessop Jan 17 '12 at 12:31
3

Yes it does it is just that the Base class = operator is hidden by the Derived class = operator.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • I'm wondering: This explanation seems incorrect to me, claims that we'd get the behavior Amit expected, and does not explain the observed behavior. Unless I'm completely misreading it, of course. Why the upvotes? – Christopher Creutzig Jan 17 '12 at 12:05
2

Unless I misunderstand what you want to achieve, you need an assignment operator for class Derived, i.e. one that takes Derived as the input:

class Derived : public Base  
{  
/* ... */
public:
    Derived& operator=(const Derived &rhs)  
    {  
        cout << "Assignment operator in Derived"<< endl;  
        return *this;  
    }
};  

What happened within your code (already explained in the answer of Bo Persson and comments there): in Derived, you implemented an assignment operator that takes an instance of Base; but in main() you assign an instance of Derived; the compiler saw no assignment operator for Derived (the one that takes Base does not count), and so it generated one, which calls Base::operator=() and then assignments for Derived's data members. If you defined the assignment as shown above, it would not happen and your operator would be called; notice that in this case assignments of Base and data members would not happen automatically.


A different situation is if you really wish to have an assignment from Base to Derived, e.g. to use it with other derivatives of Base. Then the operator you defined will work, but in order to apply it to an instance of Derived, you need to cast this instance to Base:

Derived d1(10,20);  
Derived d2(30,40);  
d1 = static_cast<Base&>(d2);

Needless to say that the operator you defined cannot easily access data members of rhs specific to Derived: e.g. to use rhs.y you would need to "up-cast" rhs to Derived:

Derived& Derived::operator=(const Base& rhs)
{
    /* ... */
    Derived* rhs_d = dynamic_cast<Derived*>(&rhs);
    if( rhs_d )
        this->y = rhs_d->y;
}
Alexey Kukanov
  • 12,479
  • 2
  • 36
  • 55
1

Quoting from the standard (12.8.24):

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 (13.5.3). A using-declaration (7.3.3) that brings in from a base class an assignment operator with a parameter type that could be that of a copy/move assignment operator for the derived class is not considered an explicit declaration of such an operator and does not suppress the implicit declaration of the derived class operator; the operator introduced by the using-declaration is hidden by the implicitly-declared operator in the derived class.

ThomasMcLeod
  • 7,603
  • 4
  • 42
  • 80
-1

If you wanted to achieve polymorfic behavior, this means to have your base method overriden, you should have written this:

int main (){
    Derived * d1 = new Derived (10,20);  
    Derived * d2 = new Derived (30,40);
    Base * b1 = d1 ;
    Base * b2 = d2 ; 
    *b1 = *b2 ;
    *d1 = *d2 ;
} 

This will produce the following output:

 $> Assignment operator in Derived.
 $> calling Assignment operator in Base. 

So what i'm doing here it's using the c++ dynamic casting implicitly. I not completely sure if this works this way, but in order to make my point i think it will be useful. When i call the assignment operator with b1 and b2 dereferenced, the program first look for an overriden method of the function invoked on the derived class if it doesn't find any then it calls the base method class. Now, when i call the assignment operator from d1 the program casts derived to base and there's no way the program could know that *d1 stands for a Derived object, so it calls the base method.

That's all folks.

Gonzo RI
  • 71
  • 1
  • 10
  • The code is missing the class definitions needed to make sense of it, gets the output lines the wrong way round (presumably, i.e. by both reasoning & completing the code), & misses the key point: What you show here is the exact **opposite** of "polymorfic" & of "using the c++ dynamic casting implicitly" at all. If this were polymorphic, then the `*b1 = *b2` assignment would *also* report that it was calling the derived `operator=`, but it does not (once we correct for your messages being the wrong way around). (Trying to make `Base.operator=` a `virtual` method opens a different world of hurt) – underscore_d Sep 15 '18 at 18:11