Класс может предоставлять особые привилегии определенным внешним функциям или функциям-членам другого класса. Эти функции получили названия дружественных. Если функция или класс объявлены как дружественные данному классу, то такие функции или функции-члены такого класса могут осуществлять непосредственный доступ ко всем полям класса, для которого они дружественны. Дружественные функции и классы могут осуществлять прямой доступ к закрытым полям класса без использования функций-членов этого класса.
Ключевое слово friend - спецификатор функции, который дает функции- не члену класса доступ к скрытым членам класса. Он используется для того, чтобы выйти за строгие рамки типизации и сокрытия данных в С++.
Одна из причин их использования состоит втом, что некоторые функции нуждаются в привилегированном доступе более, чем к одному классу. Вторая причина - friend -функция передает все параметры через список параметров, и значение каждого из них подчинено преобразованию, совместимому с назначением. Такие преобразования применяются к явно переданным аргументам-классам и поэтому особенно полезны в случаях перегрузки оператора.
Объявление friend функции должно появляться внутри объявления класса, которому она дружественна. Имени функции предшествует ключевое слово friend, и ее объявление может находится как в public так и в private части класса, что не повлияет на значение. Функция-член одного класса может быть friend -функцией другого класса. Это происходит тогда, когда функция-член объявлена в friend классе с использованием оператора разрешения контекста для определения имени функции дружественного класса. Если все функции-члены одного класса являются friend -функциями другого класса, то это можно определить записью:
freind class имя класса
class t1 {
friend void a(); // friend-функция
int b(); // функция-член
};
class t2 {
friend int t1::b(); // функция-член класса t1 имеет доступ ко всем скрытым полям класса t2
};
class t3 {
friend class t1; // все функции-члены класса t1 имеют доступ ко всем полям класса t3
};
Рассмотрим класс matrix и класс vector. Функция умножения вектора на матрицу должна иметь доступ к private-членам обоих классов. Эта функция будет friend для обоих классов.
class matix;
class vect {
int *p;
int size;
friend vect mpy(const vect &,const matix &);
public:
};
class matrix {
int **base;
int row,column;
friend vect mpy(constr vect&,const matirx &);
};
vect mpy(const vect &v,const matrix &m) {
if(v.size!=m.row) { exit(1); }
vect ans(column);
//.....
return ans;
}
Второстепенное значение требует предварительного описания класса matrix. Оно необходимо потому, что функция mpy должна появляться в обоих классах, и использует каждый класс как тип аргумента.
Friend -функции можно рассматривать как часть общего интерфейса класса. Существует ряд ситуаций, в которых они могут быть альтернативой функциям-членам. Использование freind -функций спорно, потому что они нарушают инкапсуляцию, окружающую private члены классов. Парадигма ООП утверждает, что объекты (в С++ они - переменные класса) доступны через их public члены. Только функции-члены должны иметь доступ к скрытой реализации АТД. Это ясный и строгий принцип проектирования. Friend -функция находится на самой его границе, поскольку имеет доступ к private членам, сама не являясь функцией-членом. С ее помощью можно организовать быстрый код для доступа к подробностям реализации класса.