委托给私有部分
有时,C++ 的隐私概念让我感到困惑:-)
class Foo
{
struct Bar;
Bar* p;
public:
Bar* operator->() const
{
return p;
}
};
struct Foo::Bar
{
void baz()
{
std::cout << "inside baz\n";
}
};
int main()
{
Foo::Bar b; // error: 'struct Foo::Bar' is private within this context
Foo f;
f->baz(); // fine
}
由于 Foo::Bar
是 private
,我无法在 main 中声明
。但我可以很好地调用 Foo::Bar 中的方法。为什么这会被允许?这是意外还是有意为之?b
哦等等,它会变得更好:
Foo f;
auto x = f.operator->(); // :-)
x->baz();
尽管我不允许命名类型 Foo::Bar
,但它与 auto
一起工作得很好...
Noah 写道:
类定义中定义的类型名称不能在没有限定的情况下在类外部使用。
只是为了好玩,以下是从外部获取类型的方法:
#include <type_traits>
const Foo some_foo();
typedef typename std::remove_pointer<decltype( some_foo().operator->() )>::type Foo_Bar;
Sometimes, C++'s notion of privacy just baffles me :-)
class Foo
{
struct Bar;
Bar* p;
public:
Bar* operator->() const
{
return p;
}
};
struct Foo::Bar
{
void baz()
{
std::cout << "inside baz\n";
}
};
int main()
{
Foo::Bar b; // error: 'struct Foo::Bar' is private within this context
Foo f;
f->baz(); // fine
}
Since Foo::Bar
is private
, I cannot declare b
in main
. Yet I can call methods from Foo::Bar
just fine. Why the hell is this allowed? Was that an accident or by design?
Oh wait, it gets better:
Foo f;
auto x = f.operator->(); // :-)
x->baz();
Even though I am not allowed to name the type Foo::Bar
, it works just fine with auto
...
Noah wrote:
type names defined within a class definition cannot be used outside their class without qualification.
Just for fun, here is how you can get at the type from outside:
#include <type_traits>
const Foo some_foo();
typedef typename std::remove_pointer<decltype( some_foo().operator->() )>::type Foo_Bar;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为这是设计使然。您无法显式创建
Foo::Bar
的实例,但它可以从成员函数返回,然后您可以将其传递给其他成员函数。这使您可以隐藏类的实现细节。I think this is by design. You cannot explicitly create instance of
Foo::Bar
but it could be returned from member functions and then you could pass it to other member functions. This lets you to hide implementation details of your class.我无法提供完整的答案,但也许是一个起点。 C++ 1998 规范在第 11.3 段
[class.access]
(第 175 页)下包含以下代码示例:在此示例中,私有类型通过公共
typedef
。尽管这与通过成员函数签名发布类型不同,但它是相似的。I can't provide a full answer, but maybe a starting point. The C++ 1998 specification includes the following code example under paragraph 11.3
[class.access]
(p. 175):In this example, a private type is "published" through a public
typedef
. Although it's not the same thing as publishing a type through a member function signature, it's similar.试图在标准中找到任何可以详细说明的内容,但我找不到。我唯一能找到的是 9.9:
类型名称遵循与其他名称完全相同的范围规则。特别是,在类定义中定义的类型名称不能在没有限定的情况下在其类外部使用。
本质上,Foo::Bar 的名称是 Foo 私有的,而不是定义。因此,您可以在 Foo 之外使用 Bar,只是不能按类型引用它们,因为该名称是私有的。
成员的姓名查找规则似乎对此也有一些影响。我没有看到任何专门引用“嵌套类”的内容,因此它们不会被允许(如果我实际上找不到任何东西是因为它不存在)。
Trying to find anything in the standard that would spell it out in detail but I can't. The only thing I can find is 9.9:
Type names obey exactly the same scope rules as other names. In particular, type names defined within a class definition cannot be used outside their class without qualification.
Essentially, the name of Foo::Bar is private to Foo, not the definition. Thus you can use Bars outside of Foo, you just can't refer to them by type since that name is private.
The name lookup rules for members would also seem to have some effect on this. I don't see anything that specifically references "nested class" and thus they wouldn't be allowed to (if my lack of finding anything in fact is because it's not there).