如何解决使用自动访问类的私有结构
我发现下一个奇怪的代码可以编译并运行(在VS 2019上):
#include <iostream>
class Test
{
private:
struct Priv
{
int a;
};
public:
static Priv WeirdFunc() {return {42};};
};
int main()
{
auto val = Test::WeirdFunc();
std::cout << val.a;
}
输出为42,这里没有问题。
我看到的问题是auto关键字允许我们访问私有结构“ Priv”。 如果我尝试用Test :: Priv替换auto,则会出现编译错误,正如预期的那样。 从互联网上的文章中,我发现您必须将auto用作lambda,但从未提及这种情况。
此外,如果我尝试输出“ Test :: WeirdFunc()。a”,它也可以工作
所以我的问题是:
所有这些显然都是可怕的代码风格,但是我很好奇它是否是有效的c ++代码
解决方法
Test::WeirdFunc()
的结果为Priv
。这也是val
的自动扣除类型。 auto
关键字消除了将val
的类型 name 设置为Priv
的必要性,因此,编译器不会抱怨。结果,val
的类型为Priv
(未提及),并且有一个 public 成员a
,可以自由访问。
因此,所有问题的答案是:是,(只要您不“提及”嵌套类的名称)。
另请参阅:cpp reference on nested classes
,所以我的问题是:
- 让我们访问私有结构/类是auto的预期行为吗?
是的
- 是否允许声明返回私有结构的公共功能?
是的
- 如果它是函数的返回值(例如
Test::WeirdFunc().a
),我们是否可以访问私有结构/类?
是的
所有这些显然都是可怕的代码风格,...
不,不一定。想想例如一个容器类,它将迭代器类定义为内部嵌套类型:
class Container {
class iterator {
public:
iterator operator++();
iterator operator++(int);
};
public:
iterator begin();
iterator end();
};
这允许通过iterator
访问auto
的实例和操作,但不能直接从类外部创建实例。
您有一个公共接口,该接口通过公共接口的返回值类型公开一个类型。这实质上意味着您的API设计公开了该类的私有细节,这不是C ++语言功能的问题,而是API设计的问题。请注意,这不仅适用于auto
:
using A = decltype(Test::WeirdFunc()); // A is Test::Priv.
A a{}; // well-formed.
,
这是有效的,这就是原因:
访问说明符控制对名称的访问。
因此,您无权访问名称 Priv
,但这并不意味着您无权访问其所引用的类型。还有其他“使用它”的方法,例如使用auto
。
这并不像您想的那样疯狂。毕竟,您不能对此造成任何损害:如果您不希望公共事物返回“私有类型”的实例(实际上不是很好,但这很好),那么根本就不要这样做。 / p>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。