[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Virtual operator overloads don't seem to work?

Stuart Brockman

10/22/2008 10:09:00 PM

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::operator== . Is this correct? Have I made a mistake?
5 Answers

Sam

10/22/2008 10:30:00 PM

0

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::operator== .

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.

Stuart Brockman

10/23/2008 7:13:00 AM

0

On 22 Oct, 23:29, Sam <s...@email-scan.com> 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::operator== .
>
> 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::operator== to?
Clearly it would have to have a signature of bool
Derived::operator==(const Base &other), but how do I make sure that I
get correct behavior when doing a "Derived==Base" (I would prefer that
Base::operator== was called in this case)?

James Kanze

10/23/2008 9:21:00 AM

0

On Oct 23, 12:09 am, Stuart Brockman <stuartbrock...@gmail.com> 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::operator== . Is this correct? Have I
> made a mistake?

How could it do otherwise? Base::operator==() has a different
signature than Derived::operator==(), 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::operator==(), 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::operator==( Base const& other ) const
{
Derived const* p
= dynamic_cast< Derived const* >( &other ) ;
return p != NULL && operator==( *p ) ;
}

in addition to your normal Derived::operator==, 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:james.kanze@gmail.com
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

Sam

10/23/2008 11:04:00 AM

0

Stuart Brockman writes:

> On 22 Oct, 23:29, Sam <s...@email-scan.com> 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::operator== .
>>
>> 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::operator== to?
> Clearly it would have to have a signature of bool
> Derived::operator==(const Base &other), but how do I make sure that I
> get correct behavior when doing a "Derived==Base" (I would prefer that
> Base::operator== was called in this case)?

It depends on what your real intentions are. There are several ways of doing
that. You can define both operator==() functions in the derived class, and
provide the appropriate logic, optionally define operator==(const Derived &)
as a virtual function in the base class also. And, you can always use
dynamic_cast<>() to determine whether your const Base & object is actually
Derived. There are several ways of doing this, depending on what exactly you
need to do.

Bo Persson

10/23/2008 4:49:00 PM

0

Stuart Brockman wrote:
> On 22 Oct, 23:29, Sam <s...@email-scan.com> 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::operator== .
>>
>> 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::operator== to?
> Clearly it would have to have a signature of bool
> Derived::operator==(const Base &other), but how do I make sure that
> I get correct behavior when doing a "Derived==Base" (I would prefer
> that Base::operator== 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