______________________________________________________________________

  11   Member access control                              [class.access]

  ______________________________________________________________________

1 A member of a class can be

  --private; that is, its name can be used only by members  and  friends
    of the class in which it is declared.

  --protected; that is, its name can be used only by members and friends
    of the class in which it is declared, and by members and friends  of
    classes derived from this class (see _class.protected_).

  --public;  that  is,  its  name  can  be  used anywhere without access
    restriction.

2 Members of a class defined with  the  keyword  class  are  private  by
  default.  Members of a class defined with the keywords struct or union
  are public by default.  [Example:
  class X {
      int a;                      // X::a is private by default
  };
  struct S {
      int a;                      // S::a is public by default
  };
   --end example]

3 Access control is applied uniformly to all names,  whether  the  names
  are  referred to from declarations or expressions.  [Note: access con-
  trol   applies   to   names   nominated   by    friend    declarations
  (_class.friend_) and using-declarations (_namespace.udecl_).  ] In the
  case of overloaded function names, access control is  applied  to  the
  function  selected by overload resolution.  [Note: because access con-
  trol applies to names, if access control is applied to a typedef name,
  only  the accessibility of the typedef name itself is considered.  The
  accessibility of the entity referred to by the typedef is not  consid-
  ered.  For example,
  class A
  {
          class B { };
  public:
          typedef B BB;
  };

  void f()
  {
          A::BB x;                // OK, typedef name A::BB is public
          A::B y;                 // access error, A::B is private
  }
   --end note]

4 It  should be noted that it is access to members and base classes that
  is controlled, not their visibility.  Names of members are still visi-
  ble,  and  implicit  conversions to base classes are still considered,
  when those members and base classes are inaccessible.  The interpreta-
  tion of a given construct is established without regard to access con-
  trol.  If the interpretation established  makes  use  of  inaccessible
  member names or base classes, the construct is ill-formed.

5 All  access  controls  in  clause _class.access_ affect the ability to
  access a class member name from a particular scope.  The  access  con-
  trol  for  names used in the definition of a class member that appears
  outside of the member's class definition is done as if the entire mem-
  ber  definition  appeared in the scope of the member's class.  In par-
  ticular, access controls apply as usual to member  names  accessed  as
  part  of  a  function  return  type, even though it is not possible to
  determine the access privileges of that use without first parsing  the
  rest  of  the  function  declarator.   Similarly,  access  control for
  implicit calls to the constructors, the conversion functions,  or  the
  destructor  called  to create and destroy a static data member is per-
  formed as if these calls appeared in the scope of the member's  class.
  [Example:
  class A {
      typedef int I;              // private member
      I f();
      friend I g(I);
      static I x;
  };

  A::I A::f() { return 0; }
  A::I g(A::I p = A::x);
  A::I g(A::I p) { return 0; }
  A::I A::x = 0;
  Here,  all  the uses of A::I are well-formed because A::f and A::x are
  members of class A and g is a friend of class A.   This  implies,  for
  example,  that  access  checking  on  the  first  use  of A::I must be
  deferred until it is determined that this use of A::I is as the return
  type of a member of class A.  ]

6 In  the  definition of a member of a nested class that appears outside
  of its class definition, the name of the member may  be  qualified  by
  the  names  of  enclosing  classes of the member's class even if these
  names are private members of their enclosing classes.  [Example:

  class D {
      class E {
          static int m;
      };
  };
  int D::E::m = 1;                // OK, no access error on private E
   --end example]

7 The names in a default  argument  expression  (_dcl.fct.default_)  are
  bound at the point of declaration, and access is checked at that point
  rather than at any points of use of the default  argument  expression.
  Access  checking  for  default  arguments in function templates and in
  member functions of class templates  are  performed  as  described  in
  _temp.inst_.

  11.1  Access specifiers                            [class.access.spec]

1 Member  declarations  can  be  labeled  by an access-specifier (clause
  _class.derived_):
  access-specifier : member-specificationopt
  An access-specifier specifies the access rules for  members  following
  it  until  the  end  of the class or until another access-specifier is
  encountered.  [Example:
  class X {
      int a;                      // X::a is private by default: class used
  public:
      int b;                      // X::b is public
      int c;                      // X::c is public
  };
   --end example] Any number of access specifiers is allowed and no par-
  ticular order is required.  [Example:
  struct S {
      int a;                      // S::a is public by default: struct used
  protected:
      int b;                      // S::b is protected
  private:
      int c;                      // S::c is private
  public:
      int d;                      // S::d is public
  };
   --end example]

2 The order of allocation of data members with separate access-specifier
  labels is unspecified (_class.mem_).

3 When a member is redeclared within its class  definition,  the  access
  specified  at  its  redeclaration  shall be the same as at its initial
  declaration.  [Example:
  struct S {
          class A;
  private:
          class A { };            // error: cannot change access
  };
   --end example]

  11.2  Accessibility of base classes and base       [class.access.base]
       class members

1 If a class is declared to be a base class (clause _class.derived_) for
  another class using the public access specifier, the public members of
  the  base  class are accessible as public members of the derived class
  and protected members of the base class are  accessible  as  protected
  members  of  the  derived  class.  If a class is declared to be a base
  class for another class using the protected access specifier, the pub-
  lic  and  protected  members  of the base class are accessible as pro-
  tected members of the derived class.  If a class is declared to  be  a
  base  class  for another class using the private access specifier, the
  public and protected members of the base class are accessible as  pri-
  vate members of the derived class1).

2 In the absence of an access-specifier for  a  base  class,  public  is
  assumed  when  the  derived  class  is  declared struct and private is
  assumed when the class is declared class.  [Example:
  class B { /* ... */ };
  class D1 : private B { /* ... */ };
  class D2 : public B { /* ... */ };
  class D3 : B { /* ... */ };     // B private by default
  struct D4 : public B { /* ... */ };
  struct D5 : private B { /* ... */ };
  struct D6 : B { /* ... */ };    // B public by default
  class D7 : protected B { /* ... */ };
  struct D8 : protected B { /* ... */ };
  Here B is a public base of D2, D4, and D6, a private base of  D1,  D3,
  and D5, and a protected base of D7 and D8.   --end example]

3 [Note:  A  member  of a private base class might be inaccessible as an
  inherited member name, but accessible directly.  Because of the  rules
  on  pointer conversions (_conv.ptr_) and explicit casts (_expr.cast_),
  a conversion from a pointer to a derived class  to  a  pointer  to  an
  inaccessible  base class might be ill-formed if an implicit conversion
  is used, but well-formed if an explicit cast is used.  For example,
  class B {
  public:
          int mi;                 // nonstatic member
          static int si;          // static member
  };
  class D : private B {
  };
  class DD : public D {
          void f();
  };

  _________________________
  1)  As  specified previously in clause _class.access_, private members
  of a base class remain inaccessible even  to  derived  classes  unless
  friend  declarations  within  the  base  class declaration are used to
  grant access explicitly.

  void DD::f() {
          mi = 3;                 // error: mi is private in D
          si = 3;                 // error: si is private in D
          B  b;
          b.mi = 3;               // OK (b.mi is different from this->mi)
          b.si = 3;               // OK (b.si is different from this->si)
          B::si = 3;              // OK
          B* bp1 = this;          // error: B is a private base class
          B* bp2 = (B*)this;      // OK with cast
          bp2->mi = 3;            // OK: access through a pointer to B.
  }
   --end note]

4 A base class is said to be accessible if an invented public member  of
  the  base class is accessible.  If a base class is accessible, one can
  implicitly convert a pointer to a derived class to a pointer  to  that
  base  class  (_conv.ptr_, _conv.mem_).  [Note: it follows that members
  and friends of a class X can implicitly convert an X* to a pointer  to
  a  private  or protected immediate base class of X.  ] The access to a
  member is affected by the class in which the member  is  named.   This
  naming  class  is the class in which the member name was looked up and
  found.  [Note: this class can be explicit, e.g., when  a  qualified-id
  is  used,  or  implicit,  e.g.,  when  a  class member access operator
  (_expr.ref_) is used (including cases where  an  implicit  this->"  is
  added.   If both a class member access operator and a qualified-id are
  used to name the member (as in p->T::m), the class naming  the  member
  is  the  class  named by the nested-name-specifier of the qualified-id
  (that is, T).  If the member m is accessible when named in the  naming
  class  according  to  the  rules below, the access to m is nonetheless
  ill-formed if the type of p cannot be implicitly converted to  type  T
  (for  example,  if T is an inaccessible base class of p's class).  ] A
  member m is accessible when named in class N if

  --m as a member of N is public, or

  --m as a member of N is private, and the reference occurs in a  member
    or friend of class N, or

  --m  as a member of N is protected, and the reference occurs in a mem-
    ber or friend of class N, or in a member or  friend  of  a  class  P
    derived from N, where m as a member of P is private or protected, or

  --there exists a base class B of N that is accessible at the point  of
    reference, and m is accessible when named in class B.  [Example:

      class B;
      class A {
      private:
        int i;
        friend void f(B*);
      };
      class B : public A { };
      void f(B* p) {
        p->i = 1;                     // OK: B* can be implicitly cast to A*,
                                      // and f has access to i in A
      }
     --end example]

  11.3  Access declarations                           [class.access.dcl]

1 The  access  of a member of a base class can be changed in the derived
  class by mentioning its qualified-id in the derived class declaration.
  Such mention is called an access declaration.  The effect of an access
  declaration qualified-id ; is defined to be equivalent to the declara-
  tion using qualified-id ;.2)

2 [Example:
  class A {
  public:
      int z;
      int z1;
  };
  class B : public A {
      int a;
  public:
      int b, c;
      int bf();
  protected:
      int x;
      int y;
  };

  _________________________
  2)  Access  declarations  are  deprecated;  member  using-declarations
  (_namespace.udecl_) provide a better means of doing the  same  things.
  In earlier versions of the C++ language, access declarations were more
  limited; they were generalized and made equivalent  to  using-declara-
  tions  in  the  interest of simplicity.  Programmers are encouraged to
  use using-declarations, rather than the  new  capabilities  of  access
  declarations, in new code.

  class D : private B {
      int d;
  public:
      B::c;                       // adjust access to B::c
      B::z;                       // adjust access to A::z
      A::z1;                      // adjust access to A::z1
      int e;
      int df();
  protected:
      B::x;                       // adjust access to B::x
      int g;
  };
  class X : public D {
      int xf();
  };

  int ef(D&);
  int ff(X&);
  The  external  function ef can use only the names c, z, z1, e, and df.
  Being a member of D, the function df can use the names b,  c,  z,  z1,
  bf,  x, y, d, e, df, and g, but not a.  Being a member of B, the func-
  tion bf can use the members a, b, c, z, z1, bf, x, and y.   The  func-
  tion  xf can use the public and protected names from D, that is, c, z,
  z1, e, and df (public), and x, and g (protected).  Thus  the  external
  function  ff has access only to c, z, z1, e, and df.  If D were a pro-
  tected or private base class of X, xf would have the  same  privileges
  as before, but ff would have no access at all.  ]

  11.4  Friends                                           [class.friend]

1 A friend of a class is a function or class that is not a member of the
  class but is permitted to use the private and protected  member  names
  from  the  class.   The  name  of  a friend is not in the scope of the
  class, and the friend is not called with the member  access  operators
  (_expr.ref_)  unless  it  is a member of another class.  [Example: the
  following example illustrates  the  differences  between  members  and
  friends:
  class X {
      int a;
      friend void friend_set(X*, int);
  public:
      void member_set(int);
  };
  void friend_set(X* p, int i) { p->a = i; }
  void X::member_set(int i) { a = i; }
  void f()
  {
      X obj;
      friend_set(&obj,10);
      obj.member_set(10);
  }
   --end example]

2 Declaring a class to be a friend implies that the names of private and
  protected members from the class granting friendship can  be  accessed
  in declarations of members of the befriended class.  [Note: this means
  that access to private and protected names is also granted  to  member
  functions  of the friend class (as if the functions were each friends)
  and to the static data member definitions of the friend  class.   This
  also means that private and protected type names from the class grant-
  ing friendship can be used in the base-clause of a nested class of the
  friend  class.  However, the declarations of members of classes nested
  within the friend class cannot access the names of  private  and  pro-
  tected  members from the class granting friendship.  Also, because the
  base-clause of the friend class is not part  of  its  member  declara-
  tions,  the base-clause of the friend class cannot access the names of
  the private and protected members from the class granting  friendship.
  For example,
  class A {
          class B { };
          friend class X;
  };
  class X : A::B {                // ill-formed: A::B cannot be accessed
                                  //  in the base-clause for X
          A::B mx;                // OK: A::B used to declare member of X
          class Y : A::B {        // OK: A::B used to declare member of X
                  A::B my;        // ill-formed: A::B cannot be accessed
                                  //  to declare members of nested class of X
          };
  };
  ]  An  elaborated-type-specifier shall be used in a friend declaration
  for a class.3) A class shall not be defined in a  friend  declaration.
  [Example:
  class X {
      enum { a=100 };
      friend class Y;
  };
  class Y {
      int v[X::a];                // OK, Y is a friend of X
  };
  class Z {
      int v[X::a];                // error: X::a is private
  };
   --end example]

3 A function first declared in a friend declaration has external linkage
  (_basic.link_).  Otherwise, the function retains its previous  linkage
  (_dcl.stc_).

4 When  a  friend  declaration refers to an overloaded name or operator,
  only the function specified by the parameter types becomes  a  friend.
  A  member  function of a class X can be a friend of a class Y.  [Exam-
  ple:

  _________________________
  3) The class-key of the elaborated-type-specifier is required.

  class Y {
      friend char* X::foo(int);
      // ...
  };
   --end example]

5 A function can be defined in a friend declaration of a  class  if  and
  only  if  the class is a non-local class (_class.local_), the function
  name is unqualified, and the function has namespace scope.  [Example:
  class M {
          friend void f() { }     // definition of global f, a friend of M,
                                  // not the definition of a member function
  };
   --end example] Such a function is implicitly inline.  A friend  func-
  tion  defined  in  a  class  is in the (lexical) scope of the class in
  which it is defined.  A friend function defined outside the  class  is
  not (_basic.lookup.unqual_).

6 No storage-class-specifier shall appear in the decl-specifier-seq of a
  friend declaration.

7 A name nominated by a friend declaration shall be  accessible  in  the
  scope  of the class containing the friend declaration.  The meaning of
  the friend declaration is the  same  whether  the  friend  declaration
  appears  in  the private, protected or public (_class.mem_) portion of
  the class member-specification.

8 Friendship is neither inherited nor transitive.  [Example:
  class A {
      friend class B;
      int a;
  };
  class B {
      friend class C;
  };
  class C  {
      void f(A* p)
      {
          p->a++;                 // error: C is not a friend of A
                                  // despite being a friend of a friend
      }
  };
  class D : public B  {
      void f(A* p)
      {
          p->a++;                 // error: D is not a friend of A
                                  // despite being derived from a friend
      }
  };
   --end example]

9 If a friend declaration appears in a local class  (_class.local_)  and
  the  name  specified  is  an  unqualified name, a prior declaration is
  looked up without considering scopes that are  outside  the  innermost

  enclosing  non-class  scope.   For  a  friend function declaration, if
  there is no prior declaration,  the  program  is  ill-formed.   For  a
  friend  class declaration, if there is no prior declaration, the class
  that is specified belongs to the innermost enclosing non-class  scope,
  but  if  it  is subsequently referenced, its name is not found by name
  lookup until a matching  declaration  is  provided  in  the  innermost
  enclosing nonclass scope.  [Example:
  class X;
  void a();
  void f() {
      class Y;
      extern void b();
      class A {
          friend class X;         // OK, but X is a local class, not ::X
          friend class Y;         // OK
          friend class Z;         // OK, introduces local class Z
          friend void a();        // error, ::a is not considered
          friend void b();        // OK
          friend void c();        // error
      };
      X *px;                      // OK, but ::X is found
      Z *pz;                      // error, no Z is found
  }
   --end example]

  11.5  Protected member access                        [class.protected]

1 When  a  friend  or  a member function of a derived class references a
  protected nonstatic member of a base class, an access check applies in
  addition to those described earlier in clause _class.access_.4) Except
  when forming a pointer to member (_expr.unary.op_), the access must be
  through a pointer to, reference to, or object  of  the  derived  class
  itself  (or  any  class derived from that class) (_expr.ref_).  If the
  access is to form a pointer to member, the nested-name-specifier shall
  name the derived class (or any class derived from that class).  [Exam-
  ple:
  class B {
  protected:
      int i;
      static int j;
  };

  class D1 : public B {
  };

  class D2 : public B {
      friend void fr(B*,D1*,D2*);
      void mem(B*,D1*);
  };

  _________________________
  4) This additional check does not apply to other members, e.g.  static
  data members or enumerator member constants.

  void fr(B* pb, D1* p1, D2* p2)
  {
      pb->i = 1;                  // ill-formed
      p1->i = 2;                  // ill-formed
      p2->i = 3;                  // OK (access through a D2)
      p2->B::i = 4;               // OK (access through a D2, even though
                                  //     naming class is B)
      int B::* pmi_B = &B::i;     // ill-formed
      int B::* pmi_B2 = &D2::i;   // OK (type of &D2::i is int B::*)
      B::j = 5;                   // OK (because refers to static member)
      D2::j =6;                   // OK (because refers to static member)
  }
  void D2::mem(B* pb, D1* p1)
  {
      pb->i = 1;                  // ill-formed
      p1->i = 2;                  // ill-formed
      i = 3;                      // OK (access through this)
      B::i = 4;                   // OK (access through this, qualification ignored)
      int B::* pmi_B = &B::i;     // ill-formed
      int B::* pmi_B2 = &D2::i;   // OK
      j = 5;                      // OK (because j refers to static member)
      B::j = 6;                   // OK (because B::j refers to static member)
  }
  void g(B* pb, D1* p1, D2* p2)
  {
      pb->i = 1;                  // ill-formed
      p1->i = 2;                  // ill-formed
      p2->i = 3;                  // ill-formed
  }
   --end example]

  11.6  Access to virtual functions                  [class.access.virt]

1 The access rules (clause _class.access_) for a  virtual  function  are
  determined  by its declaration and are not affected by the rules for a
  function that later overrides it.  [Example:
  class B {
  public:
      virtual int f();
  };

  class D : public B {
  private:
      int f();
  };

  void f()
  {
      D d;
      B* pb = &d;
      D* pd = &d;

      pb->f();                    // OK: B::f() is public,
                                  // D::f() is invoked
      pd->f();                    // error: D::f() is private
  }
   --end example] Access is checked at the call point using the type  of
  the expression used to denote the object for which the member function
  is called B* in the example above).  The access of the member function
  in  the  class  in  which it was defined D in the example above) is in
  general not known.

  11.7  Multiple access                                    [class.paths]

1 If a name can be reached by several paths through a  multiple  inheri-
  tance  graph,  the  access is that of the path that gives most access.
  [Example:
  class W { public: void f(); };
  class A : private virtual W { };
  class B : public virtual W { };
  class C : public A, public B {
      void f() { W::f(); }        // OK
  };
  Since W::f() is available to C::f() along the public path  through  B,
  access is allowed.  ]

  11.8  Nested classes                               [class.access.nest]

1 The  members of a nested class have no special access to members of an
  enclosing class, nor to classes or functions that have granted friend-
  ship   to   an   enclosing  class;  the  usual  access  rules  (clause
  _class.access_) shall be obeyed.  The members of  an  enclosing  class
  have  no special access to members of a nested class; the usual access
  rules (clause _class.access_) shall be obeyed.  [Example:
  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
      }
  };

   --end example]

2 [Note: because a base-clause for a nested class is part of the  decla-
  ration of the nested class itself (and not part of the declarations of
  the members of the nested class), the base-clause  may  refer  to  the
  private members of the enclosing class.  For example,
  class C {
          class A { };
          A *p;                   // OK
          class B : A             // OK
          {
                  A    *q;        // OK because of injection of name A in A
                  C::A *r;        // error, C::A is inaccessible
                  B    *s;        // OK because of injection of name B in B
                  C::B *t;        // error, C::B is inaccessible
          };
  };
   --end note]