public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: pure virtual functions and name injection
@ 2006-03-07 13:24 Pierre Chatelier
  0 siblings, 0 replies; 7+ messages in thread
From: Pierre Chatelier @ 2006-03-07 13:24 UTC (permalink / raw)
  To: gcc-help

>>  The two functions have different prototypes, I thought that the  
>> compiler was able to differentiate them.
>> Different prototypes, but the same name. The name is what is  
>> causing the error, not the rest of the signature.
>
> Ok, i guess this is because of the same name, but why is it ok with  
> the C++ standard?
> operator++(int) and operator++() do have the same name, but they  
> are considered as different by a c++ compiler...
Yes, but here it is a problem of visibility, not of resolving.

I think that the point is here :
>> It's a safety feature

> so when calling a::foo() the compiler should redirect the call to  
> the implementation d::foo(), no?
No, when you use the :: operator on a super-class, you explicitely  
ask not to use the "dynamic binding". Otherwise, it would be  
impossible to call the code of super-class
Take that simple example :

struct A
{
   virtual int f(void) {return 1;}
};

struct B : public A
{
   virtual int f(void) {return A::f();} //fortunately, it does not  
call B::f(), or it would be indefinitely recursive
};

Pierre Chatelier

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: pure virtual functions and name injection
  2006-03-07  9:28 Jérôme Cornet
@ 2006-03-07 16:17 ` John Love-Jensen
  0 siblings, 0 replies; 7+ messages in thread
From: John Love-Jensen @ 2006-03-07 16:17 UTC (permalink / raw)
  To: Jérôme Cornet, MSX to GCC

Hi Jérôme,

> Ok, i guess this is because of the same name...

Yes, that is correct.

>...but why is it ok with the C++ standard?
> operator++(int) and operator++() do have the same name, but they are
> considered
> as different by a c++ compiler...

I'm not sure.  I suspect it's a C legacy allowance.  A kluge.  A wart in the
C++ standard.

> Technically, a::foo() is not "defined" anywhere (i understand what
> you mean),
> but it does not need to, since it is a pure virtual functions.
> But a::foo() is "implemented" in class "d" (return 1), so when
> calling a::foo() the
> compiler should redirect the call to the implementation d::foo(), no?

No.

a::foo() is not d::foo().

foo() goes through the virtual function table.  a::foo() is explicitly
a::foo().

HTH,
--Eljay

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: pure virtual functions and name injection
@ 2006-03-07  9:28 Jérôme Cornet
  2006-03-07 16:17 ` John Love-Jensen
  0 siblings, 1 reply; 7+ messages in thread
From: Jérôme Cornet @ 2006-03-07  9:28 UTC (permalink / raw)
  To: gcc-help

Hello,

i saw this message here on the mailing list archive:

http://gcc.gnu.org/ml/gcc-help/2006-03/msg00027.html

and followed the thread with great interest.

John Love-Jensen wrote:

> > The two functions have different prototypes, I thought that the  
> compiler was
> able to differentiate them.
>
> Different prototypes, but the same name.  The name is what is  
> causing the
> error, not the rest of the signature.

Ok, i guess this is because of the same name, but why is it ok with  
the C++ standard?

operator++(int) and operator++() do have the same name, but they are  
considered
as different by a c++ compiler...

> To avoid this kind of situation, I recommend using a different  
> method name
> for the method with the different signature.
>
> >Then it compiles but there is a *link* error !  Can somebody  
> explain me what
> happens ?
>
> You have not defined the a::foo function anywhere.  So there is a link
> error.

Technically, a::foo() is not "defined" anywhere (i understand what  
you mean),
but it does not need to, since it is a pure virtual functions.
But a::foo() is "implemented" in class "d" (return 1), so when  
calling a::foo() the
compiler should redirect the call to the implementation d::foo(), no?

jérôme cornet

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: pure virtual functions and name injection
  2006-03-06 21:28   ` Pierre Chatelier
@ 2006-03-06 21:38     ` John Love-Jensen
  0 siblings, 0 replies; 7+ messages in thread
From: John Love-Jensen @ 2006-03-06 21:38 UTC (permalink / raw)
  To: Pierre Chatelier, MSX to GCC

Hi Pierre,

> I agree, but what surprised me is that it is necessary. I have a long
> experience with C++, and it is the first time that I do not
> understand why it can't resolve a name.

The name (with a different signature) in the child class obscures the name
in the parent class.

The language does not provide the kind of "implicit overloading" you were
relying.  It's a safety feature, such that if you add a function to the
parent class that already had the same name in a derived class, varying only
in signature, that you are aware of the potential error.

The using directive can be used to pull the name forward.

> But gcc internally use name mangling according to the prototype,
> right ? So that I would have expect a real call to foo() to be
> explicit enough to resolve.

It's not a name mangling issue.

It's a visibility issue.

Child class b is hiding the name that is present in parent class a.

> Certainly, but in this case, I was rather expecting a compile error,
> claiming that the pure virtual method had no body. On the contrary,
> gcc has accepted it, so that I thought that it has found the right foo
> () !

You can have pure virtual methods that provide a body.  That's useful if
you'd want to provide the functionality for the pure virtual because it does
the right thing in the general case, but the derived classes can still
override it for their particular cases.

You still have to override the function in the child class.  You invoke the
parent method just as you did:  a::foo()

HTH,
--Eljay

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: pure virtual functions and name injection
  2006-03-06 21:11 ` John Love-Jensen
@ 2006-03-06 21:28   ` Pierre Chatelier
  2006-03-06 21:38     ` John Love-Jensen
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre Chatelier @ 2006-03-06 21:28 UTC (permalink / raw)
  To: gcc-help

Thanks for the answer, but everything is not yet absolutely clear to me:

>> Why should I inject the "foo" name from a into b ?
> So that the compiler can find b::foo();
I agree, but what surprised me is that it is necessary. I have a long  
experience with C++, and it is the first time that I do not  
understand why it can't resolve a name. It is a use of "using" that I  
was not aware of.

> Different prototypes, but the same name.  The name is what is  
> causing the error, not the rest of the signature.
But gcc internally use name mangling according to the prototype,  
right ? So that I would have expect a real call to foo() to be  
explicit enough to resolve.

> To avoid this kind of situation, I recommend using a different  
> method name for the method with the different signature.
Agreed, but my problem here is to understand before :-)

>> Then it compiles but there is a *link* error !  Can somebody  
>> explain me what happens ?
> You have not defined the a::foo function anywhere.  So there is a  
> link error.
Certainly, but in this case, I was rather expecting a compile error,  
claiming that the pure virtual method had no body. On the contrary,  
gcc has accepted it, so that I thought that it has found the right foo 
() !

Regards,

Pierre Chatelier

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: pure virtual functions and name injection
  2006-03-06 21:02 Pierre Chatelier
@ 2006-03-06 21:11 ` John Love-Jensen
  2006-03-06 21:28   ` Pierre Chatelier
  0 siblings, 1 reply; 7+ messages in thread
From: John Love-Jensen @ 2006-03-06 21:11 UTC (permalink / raw)
  To: Pierre Chatelier, MSX to GCC

Hi Pierre,

> Why should I inject the "foo" name from a into b ?

So that the compiler can find b::foo();

> The two functions have different prototypes, I thought that the compiler was
able to differentiate them.

Different prototypes, but the same name.  The name is what is causing the
error, not the rest of the signature.

To avoid this kind of situation, I recommend using a different method name
for the method with the different signature.

>Then it compiles but there is a *link* error !  Can somebody explain me what
happens ?

You have not defined the a::foo function anywhere.  So there is a link
error.

HTH,
--Eljay

^ permalink raw reply	[flat|nested] 7+ messages in thread

* pure virtual functions and name injection
@ 2006-03-06 21:02 Pierre Chatelier
  2006-03-06 21:11 ` John Love-Jensen
  0 siblings, 1 reply; 7+ messages in thread
From: Pierre Chatelier @ 2006-03-06 21:02 UTC (permalink / raw)
  To: gcc-help

Hello,

I have posted a message in the gcc mailing list, but it appears that  
what I thought that was a bug is in fact a misunderstanding of mine.
Here is the message:
http://gcc.gnu.org/ml/gcc/2006-03/msg00195.html

It can be summarized in "the following code does not compile"

//-------------------------------------
struct a
{
   virtual int foo() =0;
   virtual ~a(){}
};

struct b : public a
{
   virtual int foo(int a) =0;
   virtual ~b(){}
};

struct c : public b
{
int test()
{
return (foo() + // <--- the compiler claims here that it cannot find  
foo()
foo(2));
}
virtual ~c(){}
};

struct d : public c
{
   virtual int foo() {return 1;}
   virtual int foo(int a) {return a;}
   virtual ~d(){}
};

int main()
{
   d call;
   return call.test();
}
//-------------------------------------

The answer is  http://gcc.gnu.org/ml/gcc/2006-03/msg00196.html

> This is not a bug in gcc.  foo in b hides the one from a.
> You can "fix" the source by:
> struct b : public a
> {
>   virtual int foo(int a) =0;
>   using a::foo;
>   virtual ~b(){}
> };
>
> Which interjects foo from a into b's "namespace".

That's ok, but I do not understand what's going on. Why should I  
inject the "foo" name from a into b ? The two functions have  
different prototypes, I thought that the compiler was able to  
differentiate them.

Here is a follow-up to that problem:
if I *do not* use "using  a::foo;" but rather replaces
	return (foo() + foo(2));
by
	return (a::foo() + foo(2));
Then it compiles but there is a *link* error !
Can somebody explain me what happens ?

Thanks in advance,

Pierre Chatelier

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2006-03-07 16:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-03-07 13:24 pure virtual functions and name injection Pierre Chatelier
  -- strict thread matches above, loose matches on Subject: below --
2006-03-07  9:28 Jérôme Cornet
2006-03-07 16:17 ` John Love-Jensen
2006-03-06 21:02 Pierre Chatelier
2006-03-06 21:11 ` John Love-Jensen
2006-03-06 21:28   ` Pierre Chatelier
2006-03-06 21:38     ` John Love-Jensen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).