Дополнительная проверка доступа, помимо описанных ранее в пункте [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 ]
Эта дополнительная проверка не применяется к другим членам, например, статическим элементам данных или константам элементов перечислителя.