14 Member access control [class.access]

14.4 Protected member access [class.protected]

Дополнительная проверка доступа, помимо описанных ранее в пункте [class.access] , применяется, когда нестатический член данных или нестатическая функция-член является защищенным членом своего класса именования ([class.access.base]).115 Как описано ранее, доступ к защищенному члену предоставляется, потому что возникает ссылка у друга или члена какого-то класса C. Если доступ должен формировать указатель на member ([expr.unary.op]), то nested-name-specifierдолжен обозначать C или класс, производный от C. Все другие обращения включают (возможно, неявный) object expression. В этом случае класс объектного выражения должен быть C классом, производным от C. [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;                    // ill-formed
  p1->i = 2;                    // ill-formed
  p2->i = 3;                    // OK (access through a D2)
  p2->B::i = 4;                 // OK (access through a D2, even though naming class is B)
  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;                     // ill-formed (not a friend of naming class B)
  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)
  int B::* pmi_B = &B::i;       // ill-formed
  int B::* pmi_B2 = &D2::i;     // OK
  j = 5;                        // OK (because j refers to static member)
  B::j = 6;                     // OK (because B​::​j 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]

Эта дополнительная проверка не применяется к другим членам, например, статическим элементам данных или константам элементов перечислителя.