14 Member access control [class.access]

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

Если класс объявлен как принадлежащий base class другому классу с использованием public спецификатора доступа, public члены базового класса доступны как public члены производного класса, а protected члены базового класса доступны как protected члены производного класса. Если класс объявлен базовый класс для другого класса , используя protected спецификатор доступа, то public и protected члены базового класса доступны в качестве protected членов производного класса. Если класс объявлен базовый класс для другого класса , используя private спецификатор доступа, то public и protected члены базового класса доступны в качестве private членов производного класса114.

При отсутствии access-specifier для базового класса public предполагается, когда производный класс определяется с помощью, class-key struct и private предполагается, когда класс определяется с помощью class-key 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 { /* ... */ };

Вот B это общественная база D2, D4и D6, собственная база D1, D3и D5, и защищенная база D7 и D8. ]end example

[ Note: Член частного базового класса может быть недоступен как унаследованное имя члена, но доступен напрямую. Из-за правил для pointer conversions и explicit castsпреобразование указателя на производный класс в указатель на недоступный базовый класс может быть плохо сформированным, если используется неявное преобразование, но правильно сформированным, если используется явное приведение. Например,

class B {
public:
  int mi;                       // non-static 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;                     // 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]

Базовый класс B из N находится accessible в R, если

  • изобретенный публичный член B мог бы быть публичным членом N, или

  • R происходит в члене или друге класса N, а изобретенный публичный член B мог бы быть частным или защищенным членом N, или

  • R происходит в члене или друге класса, P производного от N, и изобретенный открытый член B будет частным или защищенным членом P, или

  • существует такой класс S , который B является базовым классом, S доступным в, R и S базовым классом, N доступным в R.

[Example:

class B {
public:
  int m;
};

class S: private B {
  friend class N;
};

class N: private S {
  void f() {
    B* p = this;    // OK because class S satisfies the fourth condition above: B is a base class of N
                    // accessible in f() because B is an accessible base class of S and S is an accessible
                    // base class of N.
  }
};

end example]

Если базовый класс доступен, можно неявно преобразовать указатель на производный класс в указатель на этот базовый класс ([conv.ptr], [conv.mem]). [ Note: Отсюда следует, что члены и друзья класса X могут неявно преобразовывать X* в указатель на частный или защищенный непосредственный базовый класс X. ] Доступ к члену зависит от класса, в котором член назван. Этот класс именования - это класс, в котором имя члена было просмотрено и найдено. [ Этот класс может быть явным, например, когда используется, или неявным, например, когда используется оператор (включая случаи, когда добавляется неявный « »). Если оба операторы доступа члена класса и используется , чтобы назвать элемент (как в ), классе именования элемента является классом обозначать те из (то есть ). ] Член доступен в момент, когда назван в классе, если end noteNote: qualified-id class member access this->qualified-idp->T​::​mnested-name-specifierqualified-idTend notemRN

  • m как участник N является публичным, или

  • m как член N является частным и R встречается в члене или друге класса N, или

  • m поскольку член N защищен и R встречается в члене или друге класса N, или в члене класса, P производного от N, где m как член P является общедоступным, частным или защищенным, или

  • существует базовый класс B в N который доступен на R, и m доступен в R когда названный в классе 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 converted to A*, and f has access to i in A
    }

    end example]

Если оператор доступа к члену класса, включая неявный «this->», используется для доступа к нестатическому члену данных или нестатической функции-члену, ссылка имеет неправильный формат, если левый операнд (рассматриваемый как указатель в.операторе « » case) нельзя неявно преобразовать в указатель на класс именования правого операнда. [ Note: Это требование является дополнением к требованию, чтобы член был доступен с указанным именем. ]end note

Как указано ранее в разделе [class.access], частные члены базового класса остаются недоступными даже для производных классов, если только friend объявления в определении базового класса не используются для явного предоставления доступа.