Друзья (friends)
Функция operator+() не воздействует непосредственно на представление вектора. Действительно, она не может этого делать, поскольку не является членом. Однако иногда желательно дать функциям не членам возможность доступа к закрытой части класса. Например, если бы не было функции "доступа без проверки" vector::elem(), вам пришлось бы проверять индекс i на соответствие границам три раза за каждый проход цикла. Здесь мы избежали этой сложности, но она довольно типична, поэтому у класса есть механизм предоставления права доступа к своей закрытой части функциям не членам. Просто в описание класса помещается описание функции, перед которым стоит ключевое слово friend. Например, если имеется
class Vec; // Vec - имя класса
class vector { friend Vec operator+(Vec, Vec); //... };
То вы можете написать
Vec operator+(Vec a, Vec b) { int s = a.size(); if (s != b.size()) error("плохой размер вектора для +"); Vec sum = *new Vec(s); int* sp = sum.v; int* ap = a.v; int* bp = b.v; while (s--) *sp++ = *ap++ + *bp++; return sum; }
Одним из особенно полезных аспектов механизма friend является то, что функция может быть другом двух и более классов. Чтобы увидеть это, рассмотрим определение vector и matrix, а затем определение функции умножения (см. #с.8.8).
Другом класса является функция не-член, которая может использовать имена закрытых членов. Следующий пример иллюстрирует различия между членами и друзьями:
class private { int a; friend void friend_set (private*,int); public: void member_set (int); };
void friend_set (private* p,int i) { p-a=i; }
void private.member_set (int i) { a = i; }
private obj;
friend_set (obj,10);
obj.member_set (10);
Если описание friend относится к перегруженному имени или операции, то другом становится только функция с описанными типами параметров. Все функции класса cl1 могут быть сделаны друзьями класса cl2 с помощью одного описания
class cl2 { friend cl1; . . . };