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 functionint main()’:
prog.cpp:32:9: error: request for memberfoois 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?

+3


source to share


3 answers


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;
};

      

+6


source


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()

+4


source


I'm not sure why the conflict arises. Fortunately, this is pretty easy to solve:

struct D:private B, public C
{
    using C::foo;
};

      

0


source







All Articles