______________________________________________________________________

  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  and
    friends of the class in which it is declared.

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

  --public; that is, its name can be used by any function.

2 Members of a class declared with the  keyword  class  are  private  by
  default.   Members  of  a  class  declared with the keywords struct or
  union are public by default.  For example,
          class X {
              int a;  // X::a is private by default
          };
          struct S {
              int a;  // S::a is public by default
          };

3 Access control is applied uniformly to all names.

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  of  an  entire
  function  or member function to access a class member.  In particular,
  access controls apply as usual to members accessed as part of a  func­
  tion  return  type,  even  though  it is not possible to determine the
  access privileges of that use without first parsing the  rest  of  the
  function.  For 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);
          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.

  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.  For 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
          };
  Any number of access specifiers is allowed and no particular order  is
  required.  For 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
          };

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

  11.2  Access specifiers for base classes           [class.access.base]

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

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.  For 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.

3 Because of the rules on pointer conversion (_conv.ptr_), a static mem­
  ber  of  a  private  base  class might be inaccessible as an inherited
  name, but accessible directly.  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.
          }

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

  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 base class member
  is given, in the derived class, the access in effect  in  the  derived
  class  declaration at the point of the access declaration.  The effect
  of an access declaration qualified-id ; is defined to be equivalent to
  the declaration using qualified-id ;.2)

2 For 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;
          };
  _________________________
  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, rather than the new capabilities of access declarations, in
  new code.

          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 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.  The following example illus­
  trates 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);
          }

2 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.   For
  example,
          class Y {
              friend char* X::foo(int);
              // ...
          };
  All  the  functions of a class X can be made friends of a class Y by a
  single     declaration     using     an    elaborated-type-specifier3)
  _________________________
  3) Note that the class-key of  the  elaborated-type-specifier  is  re­
  quired.

  (_class.name_):
          class Y {
              friend class X;
              // ...
          };
  Declaring a class to be a friend also implies that  private  and  pro­
  tected  names  from  the  class granting friendship can be used in the
  class receiving it.  For 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
          };

3 A function declared as a friend and not previously declared, is intro­
  duced  in  the  smallest  enclosing  non-class, non-function prototype
  scope that contains the friend declaration.  For a class mentioned  as
  a friend and not previously declared, see _dcl.type.elab_.

4 A function first declared in a friend declaration has external linkage
  (_basic.link_).   Otherwise,   it   retains   its   previous   linkage
  (_dcl.stc_).   No  storage-class-specifier  shall  appear in the decl-
  specifier-seq of a friend declaration.

5 A function of namespace scope can be defined in a  friend  declaration
  of a non-local class (_class.local_).  The function is then inline.  A
  friend function 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.

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

7 Friendship is neither inherited nor transitive.  For 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
              }
          };

  11.5  Protected member access                        [class.protected]

1 A  friend  or  a  member function of a derived class can access a pro­
  tected static member, type or enumerator constant of a base class;  if
  the  access  is through a qualified-id, the nested-name-specifier must
  name the derived class (or any class derived from that class).

2 A friend or a member function of a derived class  can  access  a  pro­
  tected  nonstatic  member  of  a  base  class.   Except when forming a
  pointer to member, the access must be through a pointer to,  reference
  to,  or  object of the derived class itself (or any class derived from
  that class).  If the nonstatic protected member thus accessed is  also
  qualified, the qualification is ignored for the purpose of this access
  checking.   If  the  access  is  to   form   a   pointer   to   member
  (_expr.unary.op_),  the  nested-name-specifier  shall name the derived
  class (or any class derived from that class).  For example,
          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;  // illegal
              p1->i = 2;  // illegal
              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;    // illegal
              int B::* pmi_B = &D2::i;   // ok (type of &D2::i is "int B::*")
              B::j = 5;   // illegal
              D2::j =6;   // ok (access through a D2)
          }

          void D2::mem(B* pb, D1* p1)
          {
              pb->i = 1;  // illegal
              p1->i = 2;  // illegal
              i = 3;      // ok (access through `this')
              B::i = 4;   // ok (access through `this', qualification ignored)
              j = 5;      // ok (static member accessed by derived class function)
              B::j = 6;   // illegal
          }
          void g(B* pb, D1* p1, D2* p2)
          {
              pb->i = 1;  // illegal
              p1->i = 2;  // illegal
              p2->i = 3;  // illegal
          }

  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.  For 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
          }
  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.
  For 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.