Virtual operator overloads don't seem to work?

Discussion in 'C++' started by Stuart Brockman, Oct 22, 2008.

  1. Hi,
    I don't quite get what is going on in this code example:

    ---------------------------
    #include <iostream>

    using namespace std;

    class Base{
    public:
    virtual void Test(){
    cout << "Base" << endl;
    }

    virtual bool operator==(const Base &other){
    cout << "Base Comparison" << endl;
    return false;
    }
    };

    class Derived : public Base{
    public:
    void Test(){
    cout << "Derived" << endl;
    }

    bool operator==(const Derived &other){
    cout << "Derived Comparison" << endl;
    return true;
    }
    };

    int main(int argc, char** argv) {
    Base a; //Create a base object
    a.Test(); //Outputs "Base" as expected
    Derived b, c; //Create two derived objects
    b.Test(); //Outputs "Derived" as expected
    if(b==c) cout << "True" << endl; //Does derived comparison and
    returns true as expected.
    Base *d=&b, *e=&c; //Create two base pointers to derived objects
    d->Test(); //Outputs "Derived" as expected
    if(*d==*e) cout << "True" << endl; //Does base comparison and
    returns false!?
    return 0;
    }
    ----------------------------
    The output is:

    Base
    Derived
    Derived Comparison
    True
    Derived
    Base Comparison

    Notice, that the line "d->Test()" works correctly, but the comparison
    on the next line does not. The compiler (g++ (GCC) 4.2.3 (Ubuntu
    4.2.3-2ubuntu7) ) seems to be ignoring the virtual-ness of
    Base::eek:perator== . Is this correct? Have I made a mistake?
     
    Stuart Brockman, Oct 22, 2008
    #1
    1. Advertising

  2. On 22 Oct, 23:29, Sam <> wrote:
    > Stuart Brockman writes:
    > > Hi,
    > > I don't quite get what is going on in this code example:

    >
    > > ---------------------------
    > > #include <iostream>

    >
    > > using namespace std;

    >
    > > class Base{
    > > public:
    > >     virtual void Test(){
    > >         cout << "Base" << endl;
    > >     }

    >
    > >     virtual bool operator==(const Base &other){
    > >         cout << "Base Comparison" << endl;
    > >         return false;
    > >     }
    > > };

    >
    > > class Derived : public Base{
    > > public:
    > >     void Test(){
    > >         cout << "Derived" << endl;
    > >     }

    >
    > >     bool operator==(const Derived &other){
    > >         cout << "Derived Comparison" << endl;
    > >         return true;
    > >     }
    > > };

    >
    > > int main(int argc, char** argv) {
    > >     Base a;         //Create a base object
    > >     a.Test();       //Outputs "Base" as expected
    > >     Derived b, c;   //Create two derived objects
    > >     b.Test();       //Outputs "Derived" as expected
    > >     if(b==c) cout << "True" << endl;    //Does derived comparison and
    > > returns true as expected.
    > >     Base *d=&b, *e=&c;  //Create two base pointers to derived objects
    > >     d->Test();      //Outputs "Derived" as expected
    > >     if(*d==*e) cout << "True" << endl;  //Does base comparison and
    > > returns false!?
    > >     return 0;
    > > }
    > > ----------------------------
    > > The output is:

    >
    > > Base
    > > Derived
    > > Derived Comparison
    > > True
    > > Derived
    > > Base Comparison

    >
    > > Notice, that the line "d->Test()" works correctly, but the comparison
    > > on the next line does not. The compiler (g++ (GCC) 4.2.3 (Ubuntu
    > > 4.2.3-2ubuntu7) ) seems to be ignoring the virtual-ness of
    > > Base::eek:perator== .

    >
    > That's because "bool operator==(const Derived &)" does not polymorphically
    > overload "bool operator==(const Base &)". In a derived class, the function's
    > signature must match the base class's virtual function, in order for it to
    > be polymorphically overloaded (the function parameters must match). In your
    > case, above, you have two different functions, no different that void foo()
    > and void bar(). One does not overload the other.
    >
    > >                        Is this correct?

    >
    > Yes.
    >
    > >                                         Have I made a mistake?

    >
    > Yes, but a very natural one.
    >
    >  application_pgp-signature_part
    > < 1KViewDownload


    Ahh... I see... So what should I change Derived::eek:perator== to?
    Clearly it would have to have a signature of bool
    Derived::eek:perator==(const Base &other), but how do I make sure that I
    get correct behavior when doing a "Derived==Base" (I would prefer that
    Base::eek:perator== was called in this case)?
     
    Stuart Brockman, Oct 23, 2008
    #2
    1. Advertising

  3. Stuart Brockman

    James Kanze Guest

    On Oct 23, 12:09 am, Stuart Brockman <> wrote:

    > I don't quite get what is going on in this code example:


    > ---------------------------
    > #include <iostream>


    > using namespace std;


    > class Base{
    > public:
    > virtual void Test(){
    > cout << "Base" << endl;
    > }


    > virtual bool operator==(const Base &other){
    > cout << "Base Comparison" << endl;
    > return false;
    > }
    > };


    > class Derived : public Base{
    > public:
    > void Test(){
    > cout << "Derived" << endl;
    > }


    > bool operator==(const Derived &other){
    > cout << "Derived Comparison" << endl;
    > return true;
    > }
    > };


    > int main(int argc, char** argv) {
    > Base a; //Create a base object
    > a.Test(); //Outputs "Base" as expected
    > Derived b, c; //Create two derived objects
    > b.Test(); //Outputs "Derived" as expected
    > if(b==c) cout << "True" << endl; //Does derived comparison and
    > returns true as expected.
    > Base *d=&b, *e=&c; //Create two base pointers to derived objects
    > d->Test(); //Outputs "Derived" as expected
    > if(*d==*e) cout << "True" << endl; //Does base comparison and
    > returns false!?
    > return 0;}


    > ----------------------------
    > The output is:


    > Base
    > Derived
    > Derived Comparison
    > True
    > Derived
    > Base Comparison


    > Notice, that the line "d->Test()" works correctly, but the
    > comparison on the next line does not. The compiler (g++ (GCC)
    > 4.2.3 (Ubuntu 4.2.3-2ubuntu7) ) seems to be ignoring the
    > virtual-ness of Base::eek:perator== . Is this correct? Have I
    > made a mistake?


    How could it do otherwise? Base::eek:perator==() has a different
    signature than Derived::eek:perator==(), so the function in the
    derived class hides, rather than overloads, the function in the
    base class. Moreover, there's no way you could possibly call
    Derived::eek:perator==(), since it requires a Derived const&, and
    can't be called with a Base const& (which is basically what you
    get when you dereference a Base const*).

    In general, binary operators don't work very well with
    inheritance; what you'd really need to make them work is double
    dispatch. In the special case of == and !=, you can do
    something like:

    bool
    Derived::eek:perator==( Base const& other ) const
    {
    Derived const* p
    = dynamic_cast< Derived const* >( &other ) ;
    return p != NULL && operator==( *p ) ;
    }

    in addition to your normal Derived::eek:perator==, at least if you
    decide that two different derived types can never compare equal.
    If it makes sense for two different derived types to compare
    equal, however (say because they both represent the same value,
    but in different ways), you'll need to set up a much more
    complicated mechanism.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Oct 23, 2008
    #3
  4. Stuart Brockman

    Bo Persson Guest

    Stuart Brockman wrote:
    > On 22 Oct, 23:29, Sam <> wrote:
    >> Stuart Brockman writes:
    >>> Hi,
    >>> I don't quite get what is going on in this code example:

    >>
    >>> ---------------------------
    >>> #include <iostream>

    >>
    >>> using namespace std;

    >>
    >>> class Base{
    >>> public:
    >>> virtual void Test(){
    >>> cout << "Base" << endl;
    >>> }

    >>
    >>> virtual bool operator==(const Base &other){
    >>> cout << "Base Comparison" << endl;
    >>> return false;
    >>> }
    >>> };

    >>
    >>> class Derived : public Base{
    >>> public:
    >>> void Test(){
    >>> cout << "Derived" << endl;
    >>> }

    >>
    >>> bool operator==(const Derived &other){
    >>> cout << "Derived Comparison" << endl;
    >>> return true;
    >>> }
    >>> };

    >>
    >>> int main(int argc, char** argv) {
    >>> Base a; //Create a base object
    >>> a.Test(); //Outputs "Base" as expected
    >>> Derived b, c; //Create two derived objects
    >>> b.Test(); //Outputs "Derived" as expected
    >>> if(b==c) cout << "True" << endl; //Does derived comparison and
    >>> returns true as expected.
    >>> Base *d=&b, *e=&c; //Create two base pointers to derived objects
    >>> d->Test(); //Outputs "Derived" as expected
    >>> if(*d==*e) cout << "True" << endl; //Does base comparison and
    >>> returns false!?
    >>> return 0;
    >>> }
    >>> ----------------------------
    >>> The output is:

    >>
    >>> Base
    >>> Derived
    >>> Derived Comparison
    >>> True
    >>> Derived
    >>> Base Comparison

    >>
    >>> Notice, that the line "d->Test()" works correctly, but the
    >>> comparison on the next line does not. The compiler (g++ (GCC)
    >>> 4.2.3 (Ubuntu
    >>> 4.2.3-2ubuntu7) ) seems to be ignoring the virtual-ness of
    >>> Base::eek:perator== .

    >>
    >> That's because "bool operator==(const Derived &)" does not
    >> polymorphically overload "bool operator==(const Base &)". In a
    >> derived class, the function's signature must match the base
    >> class's virtual function, in order for it to be polymorphically
    >> overloaded (the function parameters must match). In your case,
    >> above, you have two different functions, no different that void
    >> foo() and void bar(). One does not overload the other.
    >>
    >>> Is this correct?

    >>
    >> Yes.
    >>
    >>> Have I made a mistake?

    >>
    >> Yes, but a very natural one.
    >>
    >> application_pgp-signature_part
    >> < 1KViewDownload

    >
    > Ahh... I see... So what should I change Derived::eek:perator== to?
    > Clearly it would have to have a signature of bool
    > Derived::eek:perator==(const Base &other), but how do I make sure that
    > I get correct behavior when doing a "Derived==Base" (I would prefer
    > that Base::eek:perator== was called in this case)?


    You can do that with a free function:

    bool operator==(const Derived& Left, const Base& Right)
    { return Right.operator==(Left); }


    Bo Persson
     
    Bo Persson, Oct 23, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Fabio Negri Cicotti [MCP]

    Overloads modifier

    Fabio Negri Cicotti [MCP], Dec 13, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    488
    William F. Robertson, Jr.
    Dec 13, 2004
  2. Victor Bazarov
    Replies:
    2
    Views:
    400
    red floyd
    Aug 1, 2003
  3. Replies:
    5
    Views:
    9,980
  4. Replies:
    3
    Views:
    340
    Cédric Baudry
    Jan 3, 2009
  5. Mark Seger

    Threads don't seem to work as advertised

    Mark Seger, Jul 3, 2008, in forum: Perl Misc
    Replies:
    1
    Views:
    116
    Ben Morrow
    Jul 4, 2008
Loading...

Share This Page