请参阅以下代码
struct A { using type = int; };
struct B : private A {};
struct C : B { using base_type = A; };
所有gcc 6.1,clang 3.8和msvc 2015更新3拒绝编译,因为A
不是C
内的可访问名称,因为A
是B
的私有基础{1}}。似乎gcc认为A
中using base_type = A
引用了A
的默认构造函数。 msvc和clang似乎没有。
编译错误可能是由于继承触发的名称注入(因为将using base_type = A
修改为using base_type = ::A
使所有编译器工作正常),但我想知道这个奇怪的错误是什么标准说。
更具体地说,
A::type
,A
只是一个类名(尽管gcc将其误解为函数名),它被引入C
而不是< / em> A
或B
。为什么此名称被视为B
的私人名称?答案 0 :(得分:28)
根据unqualified name lookup的规则:
(强调我的)
对于非限定名称,即不在范围解析运算符::右侧显示的名称,名称查找检查范围如下所述,直到找到至少一个任何类型的声明,此时查找停止,不再检查其他范围。
因此,首先在基类范围内找到名称A
,此处不会考虑全局命名空间中的名称。之后,执行访问权限检查,然后编译失败。
::A
指定全局范围内的名称并解决问题,使其成为qualified name lookup。
答案 1 :(得分:2)
将我的评论作为答案发布(似乎答案不仅仅是评论):
我猜这是因为A
内C
的名称查找工作原理。首先,它在使用前检查是否在A
范围内查找名称为C
的任何内容。由于它没有找到,因此它在B
的范围内进行检查,因为它是Base类。并且以防在Bs范围内找不到A,它会在global namespace
中查找。但不知何故,A
B
的私有继承在第二次查找时停止,即在B
范围内。由于它使用fully qualified
名称,这使我认为真正的问题必须在同一条线上。