C++ 外部 class 访问内部 class 的私有 - 为什么禁止

C++ Outer class access Inner class's private - why forbidden

你好我想知道为什么 C++ 标准允许我们在嵌套的 classes 中访问外部 class 的私有字段,而它禁止访问内部 class 的私有字段从外面 class。我明白,这个例子:

class OuterClass{
public:
    class InnerClass{
    public:
        void printOuterClass(OuterClass& outer) {cout << outer.m_dataToDisplay;};
    };
private:
    int m_dataToDisplay;
};

很好,因为内部 class 有时会很复杂。但我认为以下情况也可以:

class Algorithm{
public:
    class AlgorithmResults{
    public:
        void readAlgorithmResult();
    private:
        void writeAlgorithmResult();
    };

    void calculate(AlgorithmResults& results, Arguments...){
       //calculate stuff
       results.writeAlgorithmResult(results);
    }
};

对我来说,这种结构非常合理,尽管在 C++ 中不允许这样做。我还注意到,有一段时间在 Java 中都允许使用这两个示例,但现在第二个示例也被禁止了。 什么原因,第一个例子被允许,另一个例子被拒绝?

本质上,之前在该范围内声明的范围名称是有效的并且可以直接使用(除非它们被隐藏)。代码 outside 范围不能直接使用在范围内声明的名称。例如。花括号块之后的代码,不能直接使用在该块内声明的变量(间接使用的一个例子是当外部代码可以访问指向花括号块内的静态变量的指针时)。


对于第二个例子,只需将 Algorithm 设为 AlgorithmResultsfriend:

class AlgorithmResults
{
    friend class Algorithm;

嵌套的 classes 可以访问外部 class 的私有字段,因为它是外部 class 的成员,就像其他成员一样。

[class.access.nest]/1

A nested class is a member and as such has the same access rights as any other member.

另一方面,外部class对嵌套class没有特殊访问权限,它们只是正常关系。

The members of an enclosing class have no special access to members of a nested class; the usual access rules ([class.access]) shall be obeyed. [ Example:

class E {
  int x;
  class B { };

  class I {
    B b;                        // OK: E​::​I can access E​::​B
    int y;
    void f(E* p, int i) {
      p->x = i;                 // OK: E​::​I can access E​::​x
    }
  };

  int g(I* p) {
    return p->y;                // error: I​::​y is private
  }
};

— end example ]

反问:你为什么要允许它?

如果您需要外部 class 可以访问内部 class' 私有内部结构,您可以成为朋友:

    class Foo {
    public:
            class Frob {
                    friend class Foo;
                    int privateDataMember;
            };

            Foo () {
                    Frob frob;
                    frob.privateDataMember = 3735928559;
            }
    };

C++ 没有解除好友关系的方法,因此允许对外部 class 的默认私有访问会窃取您的 class 设计工具并减少默认封装。