我有以下代码
class A
{
private:
class B
{
public:
void f()
{
printf("Test");
}
};
public:
B g()
{
return B();
}
};
int main()
{
A a;
A::B b; // Compilation error C2248
A::B b1 = a.g(); //Compilation error C2248
auto b2 = a.g(); // OK
a.g(); // OK
b2.f(); // OK. Output is "Test"
}
如您所见,我有A类和私有嵌套类B. 不使用auto我不能在A之外创建A :: B的实例,但是我可以使用auto。 有人可以解释这里有什么问题吗? 我使用VC ++ 12.0,13.0,14.0(总是相同的行为)
答案 0 :(得分:6)
类型B
只能由A
和A
的朋友访问,这意味着其他代码无法引用它。另一方面,模板类型推导甚至适用于私有类型,如果您想在A
代码中使用任何形式的模板中的私有类型,则需要使用它。
auto
功能基于模板类型扣除,并遵循相同的规则,允许呼叫auto b2 = a.g();
。
答案 1 :(得分:3)
类型扣除!
当您将私有类(A::B
)嵌入到另一个类中时,只有外部类能够创建私有类型A::B
的对象。
以下声明正在尝试创建一个您无权访问A::B
的对象:
A::B b; // Compilation error C2248
A::B b1 = a.g(); //Compilation error C2248
这是因为在main()
函数中,您无法“查看”(或访问)隐藏在A
内的私有类。 auto
绕过那个。公共函数A::g()
能够创建A::B
的实例,并将其返回给您。
auto
稍后通过推断类型来解决这个问题。当编译器处理推导出auto b2 = a.g();
的类型时,它会发现类型为A::B
。这是可以的,因为A::g()
是A
的成员函数,并且可以访问A::B
。
实质上,只有A
的成员可以声明A::B
,但A::B
可以通过A
的公共成员推断A::B
}。