Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nested class access control in C++

Tags:

c++

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

like image 886
user382499 Avatar asked Jul 04 '10 02:07

user382499


2 Answers

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.

like image 120
Johannes Schaub - litb Avatar answered Nov 20 '22 04:11

Johannes Schaub - litb


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.

like image 26
AnT Avatar answered Nov 20 '22 06:11

AnT