26

请看下面的代码

struct A { using type = int; };
struct B : private A {};
struct C : B { using base_type = A; };

所有 gcc 6.1、clang 3.8 和 msvc 2015 update 3 都拒绝编译它,因为A它不是内部的可访问名称,C因为A它是B. 似乎 gcc 认为Ainusing base_type = A指的是A. msvc 和 clang 似乎没有。

也许编译错误是由于继承触发的名称注入(因为修改using base_type = Ausing base_type = ::A使所有编译器都能正常工作),但我想知道这个奇怪的错误是否是标准所说的。

更具体地说,

  1. 据我了解, not likeA::type只是A一个类名(尽管 gcc 将其误解为函数名),它被引入C not inside A nor B。为什么这个名字被认为是私有的B
  2. 这个编译错误应该被认为是一个错误,还是标准规范的边缘情况?
4

2 回答 2

28

根据不合格名称查找规则:

(强调我的)

对于未限定名称,即未出现在范围解析运算符 :: 右侧的名称,名称查找会按如下所述检查范围,直到找到至少一个任何类型的声明,此时查找停止并且没有进一步检查范围

所以名字A会首先在基类范围内找到,全局命名空间中的名字在这里不会被考虑。之后,执行访问权限检查,然后编译失败。

::A在全局范围内指定名称并解决问题,使其成为限定名称查找

于 2016-07-04T08:26:54.543 回答
2

发表我的评论作为答案(看起来更像是一个答案而不是评论):

我猜这是由于A内部名称查找的C工作方式。A首先,它检查是否在使用前的范围内使用名称声明了任何内容C。由于它没有找到一个,它正在检查它,B因为它是 Base 类。如果Bs 范围内没有找到 A,它会在global namespace. A但不知何故, by的私有继承B在第二次查找时停止,即在B. 由于它使用fully qualified名称工作,这让我认为真正的问题必须在同一行。

于 2016-07-04T08:28:43.520 回答