C ++中的嵌套类访问控制

时间:2010-07-04 02:25:27

标签: c++

内部类可以访问其封闭类的私有成员变量吗?互联网和编译器似乎存在一些矛盾。编译(gg上的cygwin)允许它。但是,一些技术文件表示不允许这样做。

4 个答案:

答案 0 :(得分:10)

没有从嵌套类授予外部类的特殊访问权。

嵌套类的C ++ 03标准的第11.8-1节:

  

嵌套类的成员有   没有特殊访问权限的成员   封闭类,也不是类或   授予友谊的功能   到封闭的班级;

class E {
    int x;
    class B { };
    class I {
        B b; // error: E::B is private
        int y;
        void f(E* p, int i)
        {
            p->x = i; // error: E::x is private
        }
    };
    int g(I* p)
    {
        return p->y; // error: I::y is private
    }
};

答案 1 :(得分:9)

Defect Report #10Defect Report #45已解决此问题。

原始和当前的C ++语言标准不授予嵌套类任何额外的访问权限,即它在访问封闭类的成员时没有特权。嵌套类只是普通的完全独立的类,恰好在其他类中声明。

但是根据缺陷报告#45中提出的解决方案,嵌套类应该被赋予对封闭类成员的完全访问权限。即嵌套类本身应被视为封闭类的成员,并应享有通常授予成员的所有访问权限。

上次检查时,有关此缺陷的工作尚未最终确定。一些编译器已经实现了他们认为新规范所需的内容,即对嵌套类的完全访问权限(参见DR#45的建议解决方案)。有些编译器坚持使用当前标准的字母。这就是为什么您可能仍然会发现不同编译器之间在授予嵌套类的访问权限方面存在一些不一致。

答案 2 :(得分:6)

在C ++ 03编译器中,这通常是允许的,因为委员会认为允许它是合乎逻辑的,因为嵌套类是其封闭类的成员。因此,他们edited the Standard允许它用于C ++ 0x(嗯,修复是在2001年完成的),并且那些编译器实现了编辑追溯作为其C ++ 03实现的一部分。

我尝试过GCC,Comeau和Clang,所有这些都允许这样做。正是通过C ++ 03规则,它的不是允许的,尽管没有编译器严格按照法律规定执行标准。


陷阱

如果你想将嵌套类声明为朋友,请注意你首先必须声明该类,然后放入好友声明

class Outer {
  friend class Inner; // wrong, refers to ::Inner
  class Inner { /* ... */ };
};

class Inner { };

您必须交换订单才能正确执行

class Outer {
  class Inner { /* ... */ };
  friend class Inner; // correct, refers to Outer::Inner
};

我已经看到过一些代码以错误的方式完成了它,但它没有被注意到,因为嵌套类无论如何都有访问权限。

另一个缺陷是Inner的所有部分都不能完全访问上面的Outer。只有Outer被视为完全定义的类的那些部分才具有此类访问权限

class Outer {
  typedef int type; // private type member

  class Inner { 
    type member; // ill-formed: no access
    void f() {
      type var; // OK: access
    }
  };

  friend class Inner; // correct, refers to Outer::Inner
};

为了能够定义member,您需要先声明它,然后再定义

class Outer {
  typedef int type; // private type member

  class Inner; // forward declaration of Outer::Inner
  friend class Inner; // correct, refers to Outer::Inner

  class Inner { 
    type member; // OK: access
    void f() {
      type var; // OK: access
    }
  };
};

要检查朋友代码,您需要一个旧的符合标准的编译器。可以使用版本 4.3.1 BETA 3/1/03 或更低版本中的Comeau Online Compiler

答案 3 :(得分:4)

C ++中的“内部”(实际上只是嵌套!)类与Java完全不同,没有特殊的状态。当然,所有外部类需要做的是声明嵌套类a friend,然后然后(就像任何其他朋友类的函数一样!)它确实获得了对私有外部类的访问权限成员。