R Справочное руководство по С++

R.11.4 Друзья.

   


Назад  |  Вперёд

Другом класса называется функция, которая не является членом класса, но в которой можно использовать частные и защищенные члены этого класса. Имя друга не принадлежит области видимости класса, и дружественная функция не вызывается с помощью операций доступа к членам ($$R.5.2.4), если только она не является членом другого класса. Следующий пример показывает различие между членами и друзьями:

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

Если в описании friend использовано имя перегруженной функции или операции, только функция, однозначно определяемая типами формальных параметров, становится другом. Функция-член класса X может быть другом класса Y, например:

           class Y {
             friend char* X::foo(int);
             // ...
           };

Можно объявить все функции класса X друзьями класса Y с помощью спецификации-сложного-типа ($$R.9.1):

           class Y {
             friend class X;
             // ...
           };

Описание одного класса как друг другого класса дополнительно подразумевает, что частные и защищенные члены класса, предлагающего дружбу, могут использоваться в классе, получающем ее, например:

           class X {
             enum { a=100 };
             friend class Y;
           };

           class Y {
             int v[X::a];   // Y друг класса X
           };

           class Z {
             int v[X::a];   // ошибка: X::a недоступно
           };

Если класс или функция, объявленные как друзья, не были описаны, их имена попадают в ту же область видимости, что и имя класса, содержащего описание friend ($$R.9.1).

Функция, появившаяся первый раз в описании friend, считается эквивалентной функции, описанной как extern ($$R.3.3, $$r.7.1.1).

Если функция-друг определена в описании класса, она считается функцией со спецификацией inline и к ней применимо правило переноса определения функции для функций-членов ($$R.9.3.2). Функция-друг, определенная в описании класса, относится на лексическом уровне к области видимости этого класса. Для функции-друга, определенной вне класса, это не так.

На описание friend не влияет указание спецификаций-доступа ($$R.9.2). Понятие дружбы не является ни наследуемым, ни транзитивным. Подтвердим это примером:

           class A {
             friend class B;
             int a;
           };

           class B {
             friend class C;
           };

           class C {
             void f(A* p);
             {
               p->a++;   // ошибка: C не друг класса A, хотя
                         // является другом друга класса A
             }
           };

           class D : public B {
             void f(A* p)
             {
               p->a++;   // ошибка: D не друг класса A, хотя
                         // является производным друга класса A
             }
           };

Назад  |  Вперёд


OtDiatlovaOU
К началу книги

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.