【问题标题】:Preventing return of private inner class instance [duplicate]防止私有内部类实例的返回[重复]
【发布时间】:2015-07-02 12:47:32
【问题描述】:

我一直在C++ 中玩内部类,现在我有点困惑。

我的代码:

#include <iostream>

class outer{
private: 
    class inner{
    private:
        int something;
    public:
        void print(){
            std::cout<< "i am inner"<<std::endl;
        }   
    };
public:
    inner returnInner(){
        inner i;
        return i;
    }  
};

int main(){
    outer o;
    //outer::inner i = o.returnInner(); (1)
    //auto i = o.returnInner();         (2)
    //i.print();                  
    o.returnInner().print();          //(3)
    return 0;
}

这是在 Linux 上使用 clang++-3.5-std=c++14 编译的。

  • (1) 中,我遇到了预期的编译器错误,因为 innerouter 的私有内部类。

  • 但是(2)中使用auto关键字时,编译成功,程序运行。

  • 一切都适用于 (3)

我的问题:

为什么会这样?我可以防止从外部方法返回私有内部类的实例,同时保留在外部类中移动和/或复制它们的能力吗?

编译器不应该像 (1) 中那样在 (2)(3) 中引发错误吗? p>

【问题讨论】:

  • 如果inner不应该从外部访问,为什么returnInner然后指定public
  • 我认为它是为了表现这种奇怪的行为。
  • @AndyG 有,但我会重新格式化以使其更清晰
  • @KunaPrime 这是一个很棒的第一个问题。欢迎来到 SO!
  • 您可以阻止复制和移动到outer 类之外,但您不能阻止例如当不涉及创建副本时绑定到引用。

标签: c++


【解决方案1】:

为什么会这样 编译器不应该像(1)一样在(2)和(3)中返回错误吗?

这是一个有趣的问题.. 这个问题的答案更有趣。

在您发布的代码中,inner是一个类型的名称name 被声明为 private,而不是 type 本身1 - type 的可访问性在 C++ 的上下文中没有意义;可访问性仅适用于 name — 类型的 name、函数的 name、数据的 name。因此,当你听到“类型 X 是一个公共类” 之类的东西时,它几乎总是意味着 “名称 X 被声明为公共的,它指的是一个类型,而类型是无所不在,无处不在”

回到为什么使用auto 不会出错,因为当您使用auto 时,您在访问类型 时不使用它的名称,这就是为什么它没有' t 给出错误。

如何防止私有内部类的实例从外部方法返回,

没有办法。


1. struct { int data; } 是一个 type,没有可引用的 name,但请注意,这不是一个有效的声明,因为它缺少 name。要么你必须声明一个 unnamed 类型的对象,如 struct { int data; } obj; 或给它一个名称 struct data_type { int data; };

【讨论】:

  • 能够在不提及其名称的情况下使用某物并没有什么特别之处。可以返回对私有成员变量的引用,然后根据需要使用它。很少有人对此感到惊讶(尽管有些人仍然如此)。
  • @Nawaz 谢谢你的回答,这是我不知道的 c++ 非常有趣的属性,而且在我看来,这会使构建 API 时的类型安全/局部性变得复杂,
  • 有趣。顺便说一句,如果我声明一个 'typedef inner inner_public ;'在公共部分,然后我可以实例化一个类型为“outer::inner_public”的变量
  • @marom,甚至更厚脸皮,使用typedef decltype(i) inner_t;auto 变量的类型命名。
  • @n.m.:我想这是因为当程序员谈论变量时,他们也会谈论创建变量的内存。并且隐式理解为只有变量可以是publicprotectedprivate;变量实际驻留的内存(或者更确切地说表示),所有人都可以通过其他方式访问,并且说内存是private 是没有意义的。但是对于 type 和它们的 name(s),没有/很少有类似的谈话可以解释它们。此外,对于某些程序,即使 type is 数据,与 data 相比,人们对类型的了解较少
【解决方案2】:

我不确定这是否是您想要的,但您可以像这样删除复制构造函数:

inner(inner const&) = delete;

【讨论】:

  • 这样一个人失去了在任何地方复制对象的能力,我想在外部执行此操作,但不想从外部方法返回内部。
  • 你可以使用另一个构造函数来复制它:D
  • 或者,inner 的构造函数可以设为私有,outer 可以成为inner 的朋友...
猜你喜欢
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 2013-04-05
  • 2013-09-20
  • 1970-01-01
  • 2012-01-04
  • 2012-12-16
相关资源
最近更新 更多