problems with operator== and inheritance

P

psane

I have the following code

#include <iostream>
#include <string>
using namespace std;

class superclass
{
public:
superclass () {}

virtual bool operator== (const superclass& rhs) const;

virtual void doit (const superclass* rhs) const;

virtual string Id () const { return "superclass";}
};

void
superclass::doit (const superclass* rhs) const
{
cout << "this->Id = " << Id () << endl;
cout << "rhs->Id = " << rhs->Id () << endl;

*this == *rhs;
}

bool
superclass::eek:perator== (const superclass& rhs) const
{
cout << "in superclass operator==" << endl;
return true;
}

///////////////////////////////////////////////////////////////////////////

class subclass : public superclass
{
public:
subclass () : superclass () {}

virtual bool operator== (const subclass& rhs) const;
#if 0
virtual bool operator== (const superclass& rhs) const;
#endif
virtual string Id () const { return "subclass";}
};

#if 0
bool
subclass::eek:perator== (const superclass& rhs) const
{
cout << "in subclass 2 operator==" << endl;
return true;
}
#endif

bool
subclass::eek:perator== (const subclass& rhs) const
{
cout << "in subclass operator==" << endl;
return true;
}
int
main (int argc, char* argv[])
{
subclass x;
subclass y;

x.doit (&y);

return 0;
}


The output I get is

this->Id = subclass
rhs->Id = subclass
in superclass operator==

However, if I change #if 0s to #if 1, I get correct (expected) output.

this->Id = subclass
rhs->Id = subclass
in subclass 2 operator==

It looks like the dynamic datatype of RHS is not being determined
correctly for operator==. Why is this so ?? How do I fix this ?? (I
really need to call doit () in the superclass ...
 
T

Thomas Matthews

psane said:
I have the following code

#include <iostream>
#include <string>
using namespace std;

class superclass
{
public:
superclass () {}

virtual bool operator== (const superclass& rhs) const;

virtual void doit (const superclass* rhs) const;

virtual string Id () const { return "superclass";}
}; [snip]

///////////////////////////////////////////////////////////////////////////

class subclass : public superclass
{
public:
subclass () : superclass () {}

virtual bool operator== (const subclass& rhs) const;
This method will be applied to explicit subclass instances, or
since it is virtual, instances of classes derived from subclass.
subclass a, b;
if (a == b) is equivalent to if(a.operator==(b))
Since b is of type "subclass", the compiler will select the
above method.
virtual bool operator== (const superclass& rhs) const;
When dealing with superclasses, this operator will be applied
when a subclass object is compared to superclass object:
superclass * p_a;
superclass * p_b;
superclass * p_c;
bool result;

p_a = new subclass;
p_b = new subclass;
p_c = new superclass;

result = *p_a == *p_b; /* calls p_a->operator==(*p_b) */
// The above statement calls
// subclass::eek:perator==(const superclass &);

result = *p_a == *p_c; /* calls p_a->operator==(*p_c) */
// The above statement calls
// subclass::eek:perator==(const superclass &);

Given another child class of superclass:
class child
: public superclass
{
};
Then the following code:
superclass * p_child = new child;
result = *p_a == *p_child;
will execute:
result = p_a->operator==(*p_child);
Which uses subclass::eek:perator==() using an instance
of the "child" class.

Dangerous.

This is why I have intentionally removed, or declared
private, the operator==() method from my base classes.
This idiom prevents an instance of one child class
from being compared to another instance.

One could workaround this issue by using Double Dispatch
or RTTI, but I don't think that is wise. I prefer to
force the users to compare apples to apples and not
apples to any fruit.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
J

John Harrison

It looks like the dynamic datatype of RHS is not being determined
correctly for operator==. Why is this so ??

Because that's how C++ works (for reasons of simplicity for compiler writers
and efficiency for the rest of us).
How do I fix this ?? (I really need to call doit () in the superclass ...

You could look up the technique known as double dispatch, but really it
would be better to find a different way.

john
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,177
Latest member
OrderGlucea
Top