C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Virtual functions and return values

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Philip
Guest





PostPosted: Thu Nov 10, 2005 5:55 pm    Post subject: Virtual functions and return values Reply with quote



The following code compiles clean on MSVC++ 7.1:

class Base
{
public:
virtual int test1(int);
virtual int test2(int);
virtual int test3(int);
virtual int test4(int);
};

class Derived : public Base
{
public:
// why no virtual function return error in following two?
int* test1(const int);
int* test2(const int&);
// uncomment to receive virtual fuunction return error
// int* test3(int);
int test4(int*);
};

int test5(int);
// uncomment to get compile error about differing only by return type
// int* test6(const int);

int test6(int);
int* test6(const int&);

void
testIt()
{
Derived derived;
int integer = 0;
// why no ambiguous call error in following two?
int* ret1 = derived.test1(integer);
int* ret2 = derived.test2(integer);
// uncomment to prove that Derived::test4 hides Base::test3
// derived.test4(integer);
derived.test4(&integer);
// uncomment to prove that test6 call is ambiguous
// test6(integer);
}

I understand why test4 will not compile and that is because the return
value differs and it is not co-variant return value.

I understand why test4 compiles and why Base::test4 is hidden (roughly
because you can't overload virtual functions).

I understand why the call to test6 is ambiguous (rougly because const&
decays away with integral types).

I don't understand why test1 and test2 compile. Is this a compiler bug
or a C++ standard quirk?

Of course specifying const int& is sort of silly, but enquiring minds
still want to know.

Philip


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
richard@ex-parrot.com
Guest





PostPosted: Thu Nov 10, 2005 8:21 pm    Post subject: Re: Virtual functions and return values Reply with quote




Philip wrote:
Quote:
The following code compiles clean on MSVC++ 7.1:

class Base
{
public:
virtual int test1(int);
virtual int test2(int);
virtual int test3(int);
virtual int test4(int);
};

class Derived : public Base
{
public:
// why no virtual function return error in following two?
int* test1(const int);

Legal. It is an entirely different function to the one in Base (which
it hides). It does not override the base function. (Incidentally, the
const here does not affect the signature, so int test1(const int) would
override the base class function.)

Quote:
int* test2(const int&);

Again, no error -- it's simply a new function.

Quote:
// uncomment to receive virtual fuunction return error
// int* test3(int);

This is legal. If your compiler gives an error, it is wrong. (Giving
a warning might be sensible, however.)

Quote:
int test4(int*);
};

int test5(int);


Quote:
// uncomment to get compile error about differing only by return type
// int* test6(const int);

int test6(int);

These two functions have the same parameters -- the top-level const is
irrelevant. (Non-template) functions of the same name cannot differ by
just their return types.

Quote:
int* test6(const int&);

void
testIt()
{
Derived derived;
int integer = 0;
// why no ambiguous call error in following two?
int* ret1 = derived.test1(integer);
int* ret2 = derived.test2(integer);

The derived name hides the one in the base class.

Quote:
// uncomment to prove that Derived::test4 hides Base::test3
// derived.test4(integer);

Yes. If you wanted them to overload each other, rather than to hide
each other, you'd have needed to have put a using declaration into the
derived class:

class Derived : public Base {
public:
using Base::test4;
int test4(int *);
};

But needing to do this often (though not always) reflects a design flaw
in your class -- do you really need them to have the same name?

Quote:
derived.test4(&integer);
// uncomment to prove that test6 call is ambiguous
// test6(integer);

Indeed. Overload resolution will not favour pass-by-const-reference
over pass-by-value (or vice versa).

Quote:
}

I understand why test4 will not compile and that is because the return
value differs and it is not co-variant return value.

I understand why test4 compiles and why Base::test4 is hidden (roughly
because you can't overload virtual functions).

You can overload virtual fuctions (though it not often a good idea).
There are three concepts involved -- overloading, overriding and
hiding:

class B {
virtual void f( int );
virtual void g( int );
virtual void h( int );
virtual void j( int );
};

class D : public B {
virtual void f( int ); // overrides B::f
virtual void g( double ); // hides B::g
using B::h;
virtual void h( double ); // overloads B::h
virtual void j( int ); // overrides B::j
virtual void j( double ); // overloads B::j
};

To overload one in a base class with one in a derived class, you either
need an explicit using declaration or you need to override the base
class function; otherwise, the derived function simply hides it.

Quote:
I understand why the call to test6 is ambiguous (rougly because const&
decays away with integral types).

It's not specific to integral types.

--
Richard Smith


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Ron Natalie
Guest





PostPosted: Thu Nov 10, 2005 8:25 pm    Post subject: Re: Virtual functions and return values Reply with quote



Philip wrote:
Quote:
The following code compiles clean on MSVC++ 7.1:

class Base
{
public:
virtual int test1(int);
virtual int test2(int);
virtual int test3(int);
virtual int test4(int);
};

class Derived : public Base
{
public:
// why no virtual function return error in following two?
int* test1(const int);
This one is an error. The const on the parameter doesn't affect

the signature. Derived::test1(const int) overrides Base::test1(int).

Quote:
int* test2(const int&);
This function has a different signature than the base. It

doesn't override Base::test2(int).


Quote:
// uncomment to get compile error about differing only by return type
// int* test6(const int);

int test6(int);

This is correct... Again the constness of the parameter itself HAS no
bearing on the signature. You have two overloads with the same
signature.

Quote:
// why no ambiguous call error in following two?
int* ret1 = derived.test1(integer);
int* ret2 = derived.test2(integer);

Because there's only one overload for function test1 and test2,
what's ambiguous?


Quote:
I don't understand why test1 and test2 compile. Is this a compiler bug
or a C++ standard quirk?

Of course specifying const int& is sort of silly, but enquiring minds
still want to know.

Other than the compiler not flagging test1's return type mismatch, I
don't see what's confusing.

int test(int);
int test(const int)
are the same function signature.


Do you know the difference between overloading and overriding and
how the name hiding really works?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Ron Natalie
Guest





PostPosted: Fri Nov 11, 2005 9:00 am    Post subject: Re: Virtual functions and return values Reply with quote

[email]richard (AT) ex-parrot (DOT) com[/email] wrote:

Quote:
// why no virtual function return error in following two?
int* test1(const int);

Legal. It is an entirely different function to the one in Base (which
it hides). It does not override the base function. (Incidentally, the
const here does not affect the signature, so int test1(const int) would
override the base class function.)

test1(const int) overrides test1(int). The const has no bearing here.
Whatever compiler he is using is broken.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Fri Nov 11, 2005 9:10 am    Post subject: Re: Virtual functions and return values Reply with quote

Philip wrote:
Quote:

I understand why the call to test6 is ambiguous (rougly because const&
decays away with integral types).

const& doesn't decay with integral types. In fact it doesn't decay ever.

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Philip
Guest





PostPosted: Sat Nov 12, 2005 10:29 am    Post subject: Re: Virtual functions and return values Reply with quote

Richard,

Thanks for the detailed reply and the concise explanation of the
difference between overriding and overloading. Also, I note that there
were a few typos in my message where I referred to the wrong member
function which you sorted out, so my thanks for that (and to the other
posters for their time and effort as well).

I got this issue compiling on MSVC 7.1, and when I compiled against gcc
3.4.4 I got much more explainable results. I then got an error for
Derived::test1, because gcc considered it to be a virtual fucntion of
Base::test1 but the returned types differed.

However, gcc accepted the Derived::test2. Here are the two signatures
(not valid code but just to illustrate).

virtual int Base::test2(int);
int* Derived::test2(const int&);

So, I regard MSVC as having a bug here. It should have produced an
error just like gcc.

Both compilers decided that Derived::test2 overrides Base::test2. I
believe because the added int reference makes the signature
sufficiently different (removing the const has no effect). I am not
sure this is correct in a pragmatic sense, because there is no real
difference in terms of outcome between above two signatures: The code
in both test2 routines does not get change the caller's data (unless a
const cast is done) so to my mind the signature is the same. But never
mind.

Lastly, you said the following:

Quote:
// uncomment to receive virtual fuunction return error
// int* test3(int);

This is legal. If your compiler gives an error, it is wrong. (Giving
a warning might be sensible, however.)

I don't believe it is legal. For virtual functions to work, the return
type has to be the same (or co-variant) so that the following works:

virtual int Base::test5(int);
int Derived::test5(int);
Base* pBase = new Derived();
int ret = pBase->test5(integer); // run-time choice of test5 routines.

Thanks again for all your help (and to the other posters), and by the
way this is not my code. I actually renamed the base functions and
removed all the base virtual qualifiers to make the class structure
less "mentally" ambiguous. That is all I could do in the time given.

Philip

"The only reason this parrot is sitting on its perch is because it is
nailed there!"


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.