[英]Why can I use auto on a private type?
我对以下代码编译并运行感到惊讶(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 << b.i;
}
这段代码编译是否正确? 为什么它是正确的? 为什么我可以在私有类型上使用auto
,而我不能使用它的名称(如预期的那样)?
auto
的规则在很大程度上与模板类型推导相同。 发布的示例与您可以将私有类型的对象传递给模板函数的原因相同:
template <typename T>
void fun(T t) {}
int main() {
Foo f;
fun(f.Baz()); // ok
}
你问为什么我们可以将私有类型的对象传递给模板函数? 因为只有类型的名称是不可访问的。 类型本身仍然可用,这就是您完全可以将其返回给客户端代码的原因。
访问控制应用于名称。 与标准中的此示例进行比较:
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
}
chill 和 R. Martinho Fernandes 已经很好地回答了这个问题。
我不能错过用哈利波特比喻回答问题的机会:
class Wizard
{
private:
class LordVoldemort
{
void avada_kedavra()
{
// scary stuff
}
};
public:
using HeWhoMustNotBeNamed = LordVoldemort;
friend class Harry;
};
class Harry : Wizard
{
public:
Wizard::LordVoldemort;
};
int main()
{
Wizard::HeWhoMustNotBeNamed tom; // OK
// Wizard::LordVoldemort not_allowed; // Not OK
Harry::LordVoldemort im_not_scared; // OK
return 0;
}
感谢 Quentin 让我想起了 Harry 的漏洞。
要添加其他(好的)答案,这里有一个来自 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
}
不禁止使用私有类型,它只是命名类型。 创建该类型的未命名临时文件是可以的,例如,在所有版本的 C++ 中。
对于其他来到这里并需要解决方法的人(例如,声明一个接受私有类型的函数),这就是我所做的:
void Func(decltype(Foo().Baz()) param) {...}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.