Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why does a base function hide a function in a derived class?

2 views
Skip to first unread message

Jia-sen

unread,
Aug 12, 2010, 9:07:00 AM8/12/10
to
It is normal that a function in derived class hides one in a base
class. But, I could explain to myself how a base function could hide
one in a derived class. Here is an example:

struct A { int x(); };
struct B : A { };
struct C : A { };
struct D : B, C {
using A::x;
int x(double);

void f();
};

void D::f() {
x(1.0); //error in gcc v4.4.0, No match for
'A::x(double)'
}

int main() { }

Isn't there a D::x(double)? I would appreciate if someone could
explain the error message.

Thanks,
Jason

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

Daniel Krügler

unread,
Aug 12, 2010, 3:48:55 PM8/12/10
to
On 12 Aug., 15:07, Jia-sen <baowei2...@gmail.com> wrote:
> It is normal that a function in derived class hides one in a base
> class. But, I could explain to myself how a base function could hide
> one in a derived class. Here is an example:
>
> struct A { int x(); };
> struct B : A { };
> struct C : A { };
> struct D : B, C {
> using A::x;
> int x(double);
>
> void f();
>
> };
>
> void D::f() {
> x(1.0); //error in gcc v4.4.0, No match for
> 'A::x(double)'
>
> }
>
> int main() { }
>
> Isn't there a D::x(double)? I would appreciate if someone could
> explain the error message.

Poor compiler-diagnostic, I guess. There *is*
D::x(double), but the primary problem is, that the
using-declaration is ambiguous, because there are
two possible A::x: One via base class B, and one
via base class C.

You should either omit the using-declaration from
D or you should pick either B::x or C::x via such
a using-declaration.

HTH & Greetings from Bremen,

Daniel Krügler

Bo Persson

unread,
Aug 12, 2010, 7:16:43 PM8/12/10
to
Jia-sen wrote:
> It is normal that a function in derived class hides one in a base
> class. But, I could explain to myself how a base function could
> hide one in a derived class. Here is an example:
>
> struct A { int x(); };
> struct B : A { };
> struct C : A { };
> struct D : B, C {
> using A::x;
> int x(double);
>
> void f();
> };
>
> void D::f() {
> x(1.0); //error in gcc v4.4.0, No match for
> 'A::x(double)'
> }
>
> int main() { }
>
> Isn't there a D::x(double)? I would appreciate if someone could
> explain the error message.
>

The compiler could be confused because there are actually two A::x
functions, one in B and one in C.

Another compiler complains about that:

Comeau C/C++ 4.3.3 (Oct 25 2003 12:02:26) for MS_WINDOWS_x86
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"X:\reference\quick_test.cpp", line 5: error: "A::x" is ambiguous
using A::x;
^

Bo Persson

Jeremy

unread,
Aug 12, 2010, 7:21:49 PM8/12/10
to
>
> Isn't there a D::x(double)? I would appreciate if someone could
> explain the error message.
>
> Thanks,
> Jason

You explicitly say 'using A::x', also you only declared D::x(double),
you did not define it so you would get an undefined reference after
removing the 'using' keyword.

Johannes Schaub (litb)

unread,
Aug 12, 2010, 7:30:33 PM8/12/10
to
Jia-sen wrote:

> It is normal that a function in derived class hides one in a base
> class. But, I could explain to myself how a base function could hide
> one in a derived class. Here is an example:
>
> struct A { int x(); };
> struct B : A { };
> struct C : A { };
> struct D : B, C {
> using A::x;
> int x(double);
>
> void f();
> };
>
> void D::f() {
> x(1.0); //error in gcc v4.4.0, No match for
> 'A::x(double)'
> }
>
> int main() { }
>
> Isn't there a D::x(double)? I would appreciate if someone could
> explain the error message.
>

I believe that there is nothing wrong with this code and it's a GCC bug.
Clang also compiles this fine. The using declaration overloads the function-
declaration in D. And "x(1.0)" will select "x(double)" of D. It would error
out if you would call "x();" only. Notice that the using declaration itself
is fine, because "A::x" refers to the member x of A, which is not in an
ambiguous subobject of A. Only when selected, the rules added by N1626 to
5.2.5p4 make it ambiguous (i believe the behavior was not specified by
C++03):

"If E2 is a non-static data member or a non-static member function, the
program is ill-formed if the class of which E2 is directly a member is an
ambiguous base (10.2) of the naming class (11.2) of E2."

(the naming class is D, and the class which x is directly a member of is A).
Notice that the new name-lookup introduced by that paper for C++0x changes
some behavior that is nowadays ill-formed, which might be interesting in
this context:

struct A { int x(); };
struct B : A { };
struct C : A { };

struct E : B, C { };
struct D : E {
using E::x;
int x(double);

void f();
};

This using-declaration is ill-formed currently, because "E::x" will find x
in two distinct subobjects and inherently cause an ambiguous lookup result.
The more logical behavior of C++0x makes this fine aswell, because the
lookup will resolve E::x to A's declaration of x. Only once called, the
result is an ambiguity by 5.2.5p4.

Johannes Schaub (litb)

unread,
Aug 13, 2010, 2:08:03 AM8/13/10
to
Johannes Schaub (litb) wrote:

By a literate interpretation of 10.2/2 in C++03, we could also go another
route. Notice that there is DR #39 which cites

"Each of these declarations that was introduced by a using-declaration is
considered to be from each sub-object of C that is of the type containing
the declaration designated by the using-declaration."

If we applied this to the lookup of "x" in "D", we would end up with "x" in
B->A, C->A and D: We would have found it in distinct subobjects and get an
ambiguity, at least this is what the DR says (using a similar example). I
don't understand how they come to that conclusion. There is wording
immediately preceeding the quoted text:

"A member name f in one sub-object B hides a member name f in a sub-object A
if A is a base class sub-object of B. Any declarations that are so hidden
are eliminated from consideration."

Since x in D hides C->A and B->A, we will not get an ambiguity, but end up
only finding the x in D. However, i fail to see the utility of considering
"x" to be of "A" for anything else than hiding base-class names relative to
the class where the using declaration appears in. I.e the "using A::x" would
hide C::x and D::x, but "D::x" should not hide "using A::x" - so we
shouldn't apply that rule, even tho a literate interpretation would force
that. In any case, without the literate and with the literate
interpretation, i can't see how compilation of the code would fail.

Miles Bader

unread,
Aug 14, 2010, 4:21:56 AM8/14/10
to
"Johannes Schaub (litb)" <schaub-...@web.de> writes:
> I believe that there is nothing wrong with this code and it's a GCC bug.
> Clang also compiles this fine.

A g++ dev snapshot[*] also compiles it fine (even with max warnings and
pickiness enabled), which does seem to suggest it's a gcc bug...

[*] g++ (Debian 20100711-1) 4.6.0 20100711 (experimental) [trunk revision 162057]

-Miles

--
Justice, n. A commodity which in a more or less adulterated condition the
State sells to the citizen as a reward for his allegiance, taxes and personal
service.

0 new messages