在c ++中使用带私有继承的声明的意外行为

Sim*_*ott 3 c++ inheritance

考虑这个小例子:

#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;
}
Run Code Online (Sandbox Code Playgroud)

使用g ++ 4.8.1编译此示例时,我收到以下错误:

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()
Run Code Online (Sandbox Code Playgroud)

我原以为D :: foo()的查找会忽略B :: foo(),因为B是私有地继承自D而且D中没有using声明.我会认为唯一可见的foo()会是A :: foo的().

但显然我认为错了,我误解了using宣言的一个方面.

谁能解释一下:

  • 为什么B :: foo()在这里可见

  • 如何使编译器只看到A :: foo()而不改变A,B或C的公共接口?

qua*_*dev 6

1)在名称查找期间忽略可访问性:成员是公共的,私有的还是受保护的并不重要:所有都被同等考虑,这就是为什么A::foo并且B::foo内部含糊不清D.

C++标准第3.4节[basic.lookup]:

访问规则(第11条)仅在名称查找和功能重载解析(如果适用)成功后才被考虑

2)简单地将其纳入以下范围D:

struct D: private B, public C
{
    using C::foo;
};
Run Code Online (Sandbox Code Playgroud)