______________________________________________________________________

  11   Member access control                    [class.access]

  ______________________________________________________________________

1 A member of a class can be

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

  --protected; that is, its name can be used only by  member  functions,
    static  data  members,  and  friends  of  the  class  in which it is
    declared and by member functions, static data 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.   In  the  case  of
  overloaded  function  names, access control is applied to the function
  selected  by  overload  resolution.   [Note:  because  access  control
  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 this clause affect  the  ability  to  access  a
  class member name from a particular scope.  In particular, access con­
  trols 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.
  [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.   --end example]

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;   // Okay, 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.

  11.1  Access specifiers                            [class.access.spec]

1 Member  declarations   can   be   labeled   by   an   access-specifier
  (_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  (_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

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

  _________________________
  1) As specified previously in _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  ac­
  cess explicitly.

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).  ] 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 or protected, and the reference occurs
    in a member or friend of class N, 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;  // Okay: 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)  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-
  declarations  in  the interest of simplicity.  Programmers are encour­
  aged to use using declarations, rather than the  new  capabilities  of
  access declarations, in new code.

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;
          };
          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 [Note:  _basic.scope.pdecl_  describes  the  point of declaration of a
  class name or a function name first introduced by  a  friend  declara­
  tion.  ]

3 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 nested classes
  cannot access the names of private  and  protected  members  from  the
  class  granting  friendship.   Also,  because  the  base-clause of the
  friend class is not part of its member declarations,  the  base-clause
  of  the  friend  class cannot access the names of the private and pro­
  tected 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 for 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:

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

          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]

4 A function first declared in a friend declaration has external linkage
  (_basic.link_).   [Note:  this  is true even if the friend declaration
  declares the function to be inline.  ] Otherwise, the function retains
  its previous linkage (_dcl.stc_).

5 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:
          class Y {
              friend char* X::foo(int);
              // ...
          };
   --end example]

6 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_).

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

8 Friend   declarations   are   not   affected   by    access-specifiers
  (_class.mem_).

9 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]

  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  this  clause.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.

          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, qualification ignored)
              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)
              j = 5;      // ok (because refers to static member)
              B::j = 6;   // ok (because 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 (_class.access_) for a virtual  function  are  deter­
  mined by its declaration and are not affected by the rules for a func­
  tion 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  func­
  tion  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 (_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
  (_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; // ill-formed: member of nested class
                  };
          };
   --end note]