开发者

nested class access control in C++

Can inner class access a private member variable of its enclosing class? There seems to be some contradiction开发者_JAVA百科s on the internet and compiler. Compile (g++ on cygwin) allows it. But, some technical documents say that it is not allowed.


No special access is granted to to the outer class from the nested class.

Section 11.8-1 of the C++03 standard on Nested classes:

The members of a nested class have no special access to members of an enclosing class, nor to classes or functions that have granted friendship to an enclosing class;

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
    }
};


This issue has been addressed in Defect Report #10 and Defect Report #45.

The original and the current C++ language standard does not grant the nested class any extra access rights, i.e. it has no privileges when accessing members of the enclosing class. Nested classes are just ordinary completely independent classes, which just happen to be declared inside some other class.

But according to the proposed resolution in the Defect Report #45, the nested class should be given full access rights to the members of the enclosing class. I.e. the nested class should itself be considered a member of the enclosing class and should enjoy all access rights normally granted to members.

Last time I checked, the work on this defect was not finalized yet. Some compilers already implement what they think the new specification will require, i.e. full access rights to nested classes (see the proposed resolution to the DR#45). Some compilers stick to the letter of the current standard. This is why you might still observe some inconsistency between different compilers with regard to access rights granted to nested classes.


In C++03 compilers this is usually allowed, because the committee figured out it would be logical to allow it, because nested classes are members of their enclosing class. Therefor they edited the Standard to allow it for C++0x (well, the fix was done at 2001), and those compilers implement that edit retroactively as part of their C++03 implementation.

I've tried GCC, Comeau and Clang, all of which allow this. Precisely by C++03 rules, it's not allowed, although no compiler out there implements the Standard strictly to the law.


Pitfalls

If you want to declare the nested class as friend, notice that you first have to declare the class, and then put the friend declaration

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

class Inner { };

You have to swap the order to do it right

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

I've seen a couple of code that has done it the wrong way, but it wasn't noticed because the nested class had access anyway.

Another pitfall is that not all parts of Inner have full access to Outer above. Only those parts where Outer is considered a completely defined class have such access

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
};

To be able to define member, you would need to first declare it and later define

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
    }
  };
};

To check the friends code you need an old conforming compiler. The Comeau Online Compiler in version 4.3.1 BETA 3/1/03 or below can be used.


An "inner" (actually, just nested!) class in C++, quite differently from Java, has no special status. Of course, all the outer class needs to do is declare that nested class a friend, and then (like any other friend class of function!) it does acquire access to private outer-class members.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜