Выбрать главу

 public:

  friend void frnd(cl ob);

  // . . .

};

Ключевое слово friend предоставляет функции, которая не является членом класса, доступ к его закрытым членам.

Как видите, ключевое слово friend предваряет остальную часть прототипа функции. Функция может быть "другом" нескольких классов.

Рассмотрим короткий пример, в котором функция-"друг" используется для доступа к закрытым членам класса myclass.

// Демонстрация использования функции-"друга".

#include <iostream>

using namespace std;

class myclass {

  int a, b;

 public:

  myclass(int i, int j) { a=i; b=j; }

  friend int sum(myclass x); // Функция sum() - "друг" класса myclass.

};

// Обратите внимание на то, что функция sum() не является членом ни одного класса

int sum(myclass х)

{

 /* Поскольку функция sum() — "друг" класса myclass, она имеет право на прямой доступ к его членам данных а и b. */

 return x.a + x.b;

}

int main ()

{

 myclass n (3, 4);

 cout << sum(n);

 return 0;

}

В этом примере функция sum() не является членом класса myclass. Тем не менее она имеет полный доступ к private-членам класса myclass. В частности, она может непосредственно использовать значения х.а и х.b. Обратите также внимание на то, что функция sum() вызывается обычным образом, т.е. без привязки к объекту (и без использования оператора "точка"). Поскольку она не функция-член, то при вызове ее не нужно квалифицировать с указанием имени объекта. (Точнее, при ее вызове нельзя задавать имя объекта.) Обычно функции-"другу" в качестве параметра передается один или несколько объектов класса, для которого она является "другом", как в случае функции sum().

Несмотря на то что в данном примере мы не извлекаем никакой пользы из объявления функции sum() "другом", а не членом класса myclass, существуют определенные обстоятельства, при которых статус функции-"друга" имеет большое значение. Во-первых, функции-"друзья" могут быть полезны для перегрузки операторов определенных типов. Во-вторых, функции-"друзья" упрощают создание некоторых функций ввода-вывода. Об этом речь впереди.

Третья причина использования функций-"друзей" состоит в том, что в некоторых случаях два (или больше) класса могут содержать члены, которые находятся во взаимной связи с другими частями программы. Например, у нас есть два различных класса, которые при возникновении определенных событий отображают на экране "всплывающие" сообщения. Другие части программы, которые предназначены для вывода данных на экран, должны знать, является ли "всплывающее" сообщение активным, чтобы случайно не перезаписать его. В каждом классе можно создать функцию-член, возвращающую значение, по которому можно судить о том, активно сообщение или нет; однако проверка этого условия потребует дополнительных затрат (т.е. двух вызовов функций вместо одного). Если статус "всплывающего" сообщения необходимо проверять часто, эти дополнительные затраты могут оказаться попросту неприемлемыми. Однако с помощью функции, "дружественной" для обоих классов, можно напрямую проверять статус каждого объекта, вызывая только одну функцию, которая будет иметь доступ к обоим классам. В подобных ситуациях функция-"друг" позволяет написать более эффективный код. Эта идея иллюстрируется на примере следующей программы.

// Использование функции-"друга".

#include <iostream>

using namespace std;

const int IDLE=0;

const int INUSE=1;

class С2; // опережающее объявление

class C1 {

  int status; // IDLE если сообщение неактивно, INUSE если сообщение выведено на экран.

  // ...

 public:

  void set_status(int state);

  friend int idle(C1 a, C2 b);

};