Click here to Skip to main content
15,889,876 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
Ok, say I have the following classes:
class MyBaseClass;
class MyDerivedClass : public MyBaseClass;

class MyBaseAssigneeClass
{
    //base class assignment operator:
    virtual MyBaseAssignableClass& operator = (const MyBaseClass& that);
};

class MyDerivedAssigneeClass : public MyBaseAssignableClass
{
    //overloaded class assignment operator:
    virtual MyDerivedAssignableClass& operator = (const MyBaseClass& that);
};

And the following code:
MyDerivedAssigneeClass MyDerivedAssigneeClassInstance;
MyDerivedClass MyDerivedClassInstance;

//should call MyDerivedAssigneeClass::operator = (const MyBaseClass&) right?
MyDerivedAssigneeClassInstance = MyDerivedClassInstance;  

Unexpectedly, it's the operator in the BASE class (MyBaseAssigneeClass) that gets called. The operator is not overloaded at all. If I change MyDerivedAssigneeClass to:
class MyDerivedAssigneeClass : public MyBaseAssignableClass
{
    //overloaded class assignment operator:
    virtual MyDerivedAssignableClass& operator = (const MyBaseClass& that);

    //Explictly overload assignment from MyDerivedClass
    //Call the other overload with that argument cast to MyBaseClass
    MyDerivedAssigneeClass& operator = (const MyDerivedClass& that) { return operator = (static_cast<const MyBaseClass&>(that)); }
};

Then it works. Have I missed something?
Posted
Updated 22-Mar-11 4:21am
v2
Comments
Sergey Alexandrovich Kryukov 22-Mar-11 12:47pm    
By the way, "overloaded" is a wrong term here. You're trying to override, which has nothing in common with overloading.
--SA
Jim @ JCT 24-Mar-11 6:03am    
Ah, yes, you are of course quite correct.

Im a little bit confused with your naming. What should i say it works as expected.
class MyBaseClass{};
class MyDerivedClass : public MyBaseClass{};

class MyBaseAssigneeClass
{
public:
    //base class assignment operator:
    virtual MyBaseAssigneeClass& operator = (const MyBaseClass& that)
    {
      _tprintf(__T("MyBaseAssigneeClass\r\n"));
      return *this;
    }
};

class MyDerivedAssigneeClass : public MyBaseAssigneeClass
{
public:
    //overloaded class assignment operator:
    virtual MyDerivedAssigneeClass& operator = (const MyBaseClass& that)
    {
      _tprintf(__T("MyDerivedAssigneeClass\r\n"));
      return *this;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
  MyDerivedAssigneeClass    MyDerivedAssigneeClassInstance;
  MyDerivedClass            MyDerivedClassInstance;

  //should call MyDerivedAssigneeClass::operator = (const MyBaseClass&) right?
  MyDerivedAssigneeClassInstance = MyDerivedClassInstance;  

  _gettch();
  return 0;
}

output:
MyDerivedAssigneeClass

Regards.
 
Share this answer
 
Comments
Dalek Dave 24-Mar-11 10:23am    
Good Answer
Try to define the = operator in the base class only and use an overridable method:

C++
class MyBaseClass
{
public:
    MyBaseClass& operator = (const MyBaseClass& that)
    {
        return Assigns(that);
    }
protected:
    virtual MyBaseClass& Assigns(const MyBaseClass& that)
    {
        ...
        return *this;
    }
};
class MyDerivedClass : public MyBaseClass
{
protected:
    virtual MyBaseClass& Assigns(const MyBaseClass& that)
    {
        ...
        return *this;
    }
};
 
Share this answer
 
Comments
Dalek Dave 24-Mar-11 10:24am    
Good Call.
Jim @ JCT 25-Mar-11 4:37am    
Yes, this is a very good approach. I'll do it this way in future.

The question remains, however - why is this necessary? Why doesn't overriding the assignment operator work as expected?
Olivier Levrey 25-Mar-11 4:50am    
Have a look to this links (an interesting discussion about that):
http://icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html
http://icu-project.org/docs/papers/cpp_report/the_assignment_operator_revisited.html
Jim @ JCT 25-Mar-11 5:53am    
Ah, thank you! That's the kind of thing I was looking for.
Thanks for the replies chaps, but gah, I've given the example wrong. Dammit, sorry. Let me try again.

C#
class MyBaseClass
{
    //base class assignment operator:
    virtual MyBaseClass& operator = (const MyBaseClass& that);
};
class MyDerivedClass : public MyBaseClass
{
    //overridden assignment operator:
    virtual MyDerivedClass& operator = (const MyBaseClass& that);
};


And the following code:

C#
MyDerivedClass MyObj1;
MyDerivedClass MyObj2;

//should call MyDerivedClass::operator = (const MyBaseClass&) right?
MyObj1 = MyObj2;  


I would have expected this to work the same as the example that mbue posted above - but in my code, it doesn't.

I would expect that MyObj2 would be implicitly cast to a MyBaseClass and the overridden assignment operator in the derived class called. But it isn't; the base class version is called. I have to add:
C#
MyDerivedClass& operator = (const MyDerivedClass& that) { return operator = (static_cast<const MyBaseClass&>(that)); }


to explicitly accept an argument of my derived class.

Again, is there something I'm missing?
 
Share this answer
 
Comments
Olivier Levrey 24-Mar-11 9:49am    
If this is a question, don't post it as an answer. Use the "Improve question" instead.
Jim @ JCT 25-Mar-11 4:48am    
OK, got you. I didn't want to change the question as someone had already answered.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900