Unexpected behavior of using private inheritance declaration in C ++
Consider this small example:
#include <iostream>
struct A
{
void foo()
{
std::cout << "A::foo" << std::endl;
}
};
struct B
{
void foo()
{
std::cout << "B::foo" << std::endl;
}
};
struct C:private A
{
using A::foo;
};
struct D:private B, public C
{
};
int main()
{
D myD;
myD.foo();
return 0;
}
When compiling this example with g ++ 4.8.1, I get the following errors:
prog.cpp: In function ‘int main()’:
prog.cpp:32:9: error: request for member ‘foo’ is ambiguous
myD.foo();
^
prog.cpp:5:10: note: candidates are: void A::foo()
void foo()
^
prog.cpp:5:10: note: void A::foo()
prog.cpp:13:10: note: void B::foo()
void foo()
I would think that searching for D :: foo () would ignore B :: foo (), because B is privately inherited from D and there is no declaration using
in D. I would think that the only visible foo () would be A :: foo ().
But I was clearly wrong and I misunderstood the aspect of the declaration using
.
Can anyone explain:
-
Why is B :: foo () visible here
-
How do I make the compiler only see A :: foo () without changing the public interfaces A, B, or C?
source to share
1) Accessibility is ignored during name lookups: it doesn't matter if the element is public, private, or protected: all are equally accounted for, A::foo
and therefore B::foo
ambiguous within D
.
C ++ 3.4 standard section [basic.lookup]:
Access rules (section 11) are only considered after successful name lookup and function overload resolution (if applicable)
2) Just put it in the scope D
:
struct D: private B, public C
{
using C::foo;
};
source to share
Why is
B::foo()
displayed here
Access restrictions do not affect the visibility of names during name lookups; they are only checked after the search has found an unambiguous match.
How do I make the compiler only see A :: foo () without changing the public interfaces A, B, or C?
Add using C::foo;
to D
. This hides any declarations with the same name in the base classes, so only one overload is visible internally D
.
Also, qualify the function call: myD.C::foo()
source to share