为什么我可以使用私人types的汽车?

我有点惊讶,下面的代码编译和运行(vc2012&gcc4.7.2)

class Foo { struct Bar { int i; }; public: Bar Baz() { return Bar(); } }; int main() { Foo f; // Foo::Bar b = f.Baz(); // error auto b = f.Baz(); // ok std::cout << bi; } 

这段代码编译正确吗? 为什么它是正确的? 为什么我可以使用autotypes,而我不能使用它的名称(如预期的)?

auto的规则大部分与模板types的扣除相同。 该示例发布的作品出于同样的原因,您可以将私有types的对象传递给模板函数:

 template <typename T> void fun(T t) {} int main() { Foo f; fun(f.Baz()); // ok } 

为什么我们可以将私有types的对象传递给模板函数呢? 因为只有types的名称是不可访问的。 types本身仍然可用,这就是为什么你可以返回到客户端代码。

访问控制应用于名称 。 从这个标准比较这个例子:

 class A { class B { }; public: typedef B BB; }; void f() { A::BB x; // OK, typedef name A::BB is public A::B y; // access error, A::B is private } 

这个问题已经被冷酷的和R.马丁尼·费尔南德斯(Martinho Fernandes)很好的回答了。

我无法放弃这个回答哈利波特比喻的问题:

 class Wizard { private: class LordVoldemort { void avada_kedavra() { // scary stuff } }; public: using HeWhoMustNotBeNamed = LordVoldemort; }; int main() { Wizard::HeWhoMustNotBeNamed tom; // OK Wizard::LordVoldemort not_allowed; // Not OK return 0; } 

为了增加其他(好的)答案,下面是一个来自C ++ 98的例子,它解释了这个问题实际上并不需要使用auto

 class Foo { struct Bar { int i; }; public: Bar Baz() { return Bar(); } void Qaz(Bar) {} }; int main() { Foo f; f.Qaz(f.Baz()); // Ok // Foo::Bar x = f.Baz(); // f.Qaz(x); // Error: error: 'struct Foo::Bar' is private } 

使用私人types不被禁止,只是命名的types。 例如,在C ++的所有版本中,创build该types的未命名临时文件都是可以的。