problems with operator== and inheritance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • psane

    problems with operator== and inheritance

    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::doi t (const superclass* rhs) const
    {
    cout << "this->Id = " << Id () << endl;
    cout << "rhs->Id = " << rhs->Id () << endl;

    *this == *rhs;
    }

    bool
    superclass::ope rator== (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::opera tor== (const superclass& rhs) const
    {
    cout << "in subclass 2 operator==" << endl;
    return true;
    }
    #endif

    bool
    subclass::opera tor== (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 ...
  • Thomas Matthews

    #2
    Re: problems with operator== and inheritance

    psane wrote:
    [color=blue]
    > 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 ";}
    > };[/color]
    [snip]
    [color=blue]
    > ///////////////////////////////////////////////////////////////////////////
    >
    > class subclass : public superclass
    > {
    > public:
    > subclass () : superclass () {}
    >
    > virtual bool operator== (const subclass& rhs) const;[/color]
    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.
    [color=blue]
    > virtual bool operator== (const superclass& rhs) const;[/color]
    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::opera tor==(const superclass &);

    result = *p_a == *p_c; /* calls p_a->operator==(*p_ c) */
    // The above statement calls
    // subclass::opera tor==(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::opera tor==() 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:

    C++ Faq: http://www.parashift.com/c++-faq-lite
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.l earn.c-c++ faq:

    Other sites:
    http://www.josuttis.com -- C++ STL Library book

    Comment

    • John Harrison

      #3
      Re: problems with operator== and inheritance

      >[color=blue]
      > It looks like the dynamic datatype of RHS is not being determined
      > correctly for operator==. Why is this so ??[/color]

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

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

      john


      Comment

      Working...