______________________________________________________________________

  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
      functions  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
          };

  11.1  Access specifiers                            [class.access.spec]

1 Member  declarations   may   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  (but see _over.dcl_).  If a class is
  declared to be a base class for  another  class  using  the  protected
  access  specifier,  the public 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 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.  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 may be inaccessible as an inherited  name,
  but accessible directly.  For example,

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

          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 the same as 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 and bp2->mi is the same as this->mi
          }

4 A base class is said to be accessible if its public members are acces­
  sible.  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 pro­
  tected immediate base class of X.

  11.3  Access declarations                           [class.access.dcl]

1 The access of public or protected member of  a  private  or  protected
  base  class  can be restored to the same level in the derived class by
  mentioning its qualified-id in the public (for public members  of  the
  base  class)  or  protected  (for protected members of the base class)
  part of a derived class declaration.  Such mention is called an access
  declaration.

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

3 An  access  declaration may not be used to restrict access to a member
  that is accessible in the base class, nor may it  be  used  to  enable
  access  to  a  member  that  is not accessible in the base class.  For
  example,
          class A {
          public:
              int z;
          };
          class B : private A {
          public:
              int a;
              int x;
          private:
              int b;
          protected:
              int c;
          };

          class D : private B {
          public:
              B::a;  // make `a' a public member of D
              B::b;  // error: attempt to grant access
                     // can't make `b' a public member of D
              A::z;  // error: attempt to grant access
          protected:
              B::c;  // make `c' a protected member of D
              B::x;  // error: attempt to reduce access
                     // can't make `x' a protected member of D
          };
          class E : protected B {
          public:
              B::a;  // make `a' a public member of E
          };
  The names c and x are protected members of E by  virtue  of  its  pro­
  tected  derivation  from  B.  An access declaration for the name of an
  overloaded function adjusts the access to all functions of  that  name
  in the base class.  For example,
          class X {
          public:
              f();
              f(int);
          };

          class Y : private X {
          public:
              X::f;  // makes X::f() and X::f(int) public in Y
          };

4 The  access  to  a  base  class member cannot be adjusted in a derived
  class that also defines a member of that name.  For example,
          class X {
          public:
              void f();
          };

          class Y : private X {
          public:
              void f(int);
              X::f;  // error: two declarations of f
          };

  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-specifier2)
  (_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 For  a  class  or  function  mentioned  as a friend and not previously
  declared, see _namespace.def_.

4 A function first declared in a friend declaration has external linkage
  (_basic.link_).   Otherwise,   it   retains   its   previous   linkage
  (_dcl.stc_).
  _________________________
  2)  Note  that  the  class-key of the elaborated-type-specifier is re­
  quired.

  +-------                 BEGIN BOX 1                -------+
  Is the following friend declaration well-formed: "friend  static  void
  f();" ?
  +-------                  END BOX 1                 -------+

5 A  function  of namespace scope may 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 of a base class.  A friend or a member function
  of a derived class can access a protected nonstatic member of  one  of
  its base classes only through a pointer to, reference to, or object of
  the derived class itself (or any class derived from that class).  When
  a  protected  member  of  a  base class appears in a qualified-id in a
  friend or a member function  of  a  derived  class,  the  nested-name-
  specifier must name the derived class.  For example,

          class B {
          protected:
              int i;
          };

          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)
              int B::*   pmi_B = &B::i;    // illegal
              int D2::*  pmi_D2 = &D2::i;  // ok
          }
          void D2::mem(B* pb, D1* p1)
          {
              pb->i = 1;  // illegal
              p1->i = 2;  // illegal
              i = 3;      // ok (access through `this')
          }
          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 f();
          };

          class D : public B {
          private:
              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.