Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка_new_ООП.doc
Скачиваний:
3
Добавлен:
09.11.2019
Размер:
133.63 Кб
Скачать

Дружественные функции

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

Тем не менее, как показывает практика, иногда необходимо получить прямой доступ к полям класса, не используя его интерфейс. Зачем это может понадобиться? Одна из причин может быть следующей: при доступе к внутренним переменным класса через его функции уменьшается эффективность работы за счет затрат на вызов функции. В большинстве случаев это не критично, но не всегда. Иногда это может играть существенную роль. Или, еще один пример, нам необходимо получить прямой доступ к внутренним данным двух разных классов.

Для решения подобного круга задач в С++ и существует возможность описания функции, функции-члена другого класса как дружественной (friend). Класс может предоставлять особые привилегии определенным внешним функциям или функциям-членам другого класса. Рассмотрим как работает этот механизм.

Для описания функции дружественной тому или иному классу, необходимо в описании этого класса объявить дружественную функцию, используя ключевое слово friend. Причем, обратите внимание, не играет никакой роли в каком из разделов класса разместить объявление дружественной функции.

class СPlayer
{
 …
 friend int F(const CPlayer &player)
}
Рисунок 17 - Объявление дружественной функции

Если обычные функции-члены имеют автоматический доступ ко всем данным своего класса за счет передачи скрытого параметра - указателя this на экземпляр класса, то дружественные функции требуют явной спецификации этого параметра. Действительно, объявленная в классе СPlayer дружественная функция F не принадлежит этому классу, а, значит, не может быть вызвана операторами player.F(), где player - экземпляр класса CPlayer. Синтаксически корректными будут обращения F (& player).

Опишем функцию, дружественную для классов CPlayer и CCircle. Пусть она возвращает истину, если объекты соответсвующих классов пересекаются и ложь – в противном случае. Функция будет иметь следующий вид:

int intersect(CPlayer &p, CCircle &o)
{
  return fabs(o.x-p.x) < 20 && fabs(o.y-p.y) < 20;
}
Рисунок 18 – Реализация функции, дружественной для классов CPlayer и CCircle

Для того, чтобы данная функция могла получить доступ к закрытым полям классов CPlayer и CCircle, необходимо в описании этих классов добавить прототип данной функции с ключевым словом friend

class СPlayer
{
 …
 friend int intersect(CPlayer &, CCircle &);
}

class СCircle
{
 …
 friend int intersect(CPlayer &, CCircle &);
}
Рисунок 19 – Описание функции, дружественной для классов CPlayer и CCircle