class A {};
class B : private A {
};
class C : public B {
public:
void f() {
A a; // This line causes error, but works when it is in main() function
}
};
int main()
{
C c;
// A a; --> This line works
return 0;
}
我猜这与B
私下继承的A
有关,但不能指责它。
编辑:错误是“A类不可见”。用g ++编译。
答案 0 :(得分:12)
名称查找与访问检查分开。当您从类继承时,该类的名称将被注入到继承类的范围中。因此,在课程C
中,您会选择名称A
,但无法访问。
一种解决方案是编写::A a;
而不是A a;
。
答案 1 :(得分:3)
虽然Alf的答案是正确的,但我觉得它可以更明确一些(或者更令人困惑,谁知道)。类的名称被注入类本身的范围。正如他提到的那样,访问说明符只有在查找后才能查找标识符的含义。在问题代码中:
class A {};
class B : private A {};
struct C : public B {
void f() {
A a; // This line causes error, but works when it is in main() function
}
};
处理C::f
时,编译器会看到标识符A
并尝试解析它。它在C
范围内搜索并且不存在,它向上移动层次结构但在B
中找不到它,但它在基类型A
中找到它(查找结果)不合格的A
为::A::A
)。在此上下文中,标识符A
被解析为我的基类B 的基类A中的注入名称A,并检查访问说明符。编译器检查它是否可以访问我的基类B ,然后它是否可以访问它的基类A 但是由于private
继承而无法访问它并抱怨您无法访问A
内的嵌套名称A
。
通过提供额外的资格::A
,您正在指导查找。在这种情况下,它将在全局命名空间中找到类型A
,它可以完全访问并且将进行编译。