Читать «Справочное руководство по C++» онлайн - страница 65

Бьярн Страустрап

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; // недопустимо

 p1-›i = 2; // недопустимо

 p2-›i = 3; // нормально (обращение через D2)

}

void D2::mem(B* pb, D1* p1)

{

 pb-›i = 1; // недопустимо

 p1-›i = 2; // недопустимо

 i = 3; // нормально (обращение через this)

}

void g(B* pb, D1* p1, D2* p2)

{

 pb-›i = 1; // недопустимо

 p1-›i = 2; // недопустимо

 p2-›i = 3; // недопустимо

}

R.11.6 Доступ к виртуальным функциям

Правила доступа (§R.11) к виртуальной функции определяются ее описанием и на них не влияют правила доступа к к функции, которая позднее будет подавлять ее. Приведем пример:

class B {

public:

 virtual f();

};

class D: public B {

private:

 f();

};

void f()

{

 D d;

 B* pb = &d;

 D* pd = &d;

 pb-›f(); // нормально: B::f() общий член

  // вызывается D::f()

 pd-›f(); // ошибка: D::f() частный член

}

Права доступа проверяются при самом вызове, используя тип выражения, обозначающее объект, для которого вызывается функция-член (в примере выше это B*). Доступ к функции-члену в классе, где она определена (D в примере выше), в общем случае неизвестен.

R.11.7 Множественный доступ

Если добраться до имени можно несколькими путями по графу, задающему множественное наследование, то право доступа этого имени считается максимальным из прав, получаемых на разных путях. Поясним это примером:

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(); } // нормально

};

Поскольку W::f() доступно в C::f() по пути, связанному с общим наследованием из B, обращение является законным.

R.12 Специальные функции-члены

Некоторые функции-члены считаются специальными, поскольку они влияют на то, как объекты класса создаются, копируются и уничтожаются, и как значения одного типа преобразуются в значения другого типа. Часто такие функции вызываются неявно.

Эти функции-члены подчиняются обычным правилам доступа (§R.11). Например, описание конструктора со спецификацией protected гарантирует, что создавать объекты с его помощью смогут только производные классы и друзья.

R.12.1 Конструкторы