微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用自动访问类的私有结构

如何解决使用自动访问类的私有结构

我发现下一个奇怪的代码可以编译并运行(在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”,它也可以工作

所以我的问题是:

  • 让我们访问私有结构/类是auto的预期行为吗?
  • 是否允许声明返回私有结构的公共功能
  • 如果它是函数的返回值(例如“ 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 举报,一经查实,本站将立刻删除。