      ______________________________________________________________________

      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,  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  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.  ]

    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  pri-
      vate members of the derived class1).
      _________________________
      1)  As  specified  previously  in _class.access_, private members of a

    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]

    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
      _________________________
      base class remain inaccessible even to derived classes  unless  friend
      declarations  within  the base class declaration are used to grant ac-
      cess explicitly.

      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 [Example:
              class A {
              public:
                  int z;
                  int z1;
              };
      _________________________
      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 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 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) The class-key of the elaborated-type-specifier is required.

    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:
              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;    // okay, but X is a local class, not ::X
                      friend class Y;    // okay
                      friend class Z;    // okay, introduces local class Z
                      friend void a();   // error, ::a is not considered
                      friend void b();   // okay
                      friend void c();   // error
                  };
                  X *px;                 // okay, 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 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:

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

              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*);
              };
              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; // okay because of injection of name A in A
                              C::A *r; // error, C::A is inaccessible
                              B    *s; // okay because of injection of name B in B
                              C::B *t; // error, C::B is inaccessible
                      };
              };
       --end note]