Напомним, что для того, чтобы функция, определенная обычным образом, получила доступ ко всем членам класса, включая закрытые, ее следует объявить дружественной, указав в теле класса ее прототип с ключевым словом friend. Функцией, дружественной классу, может быть как произвольная внешняя функция, так и составная функция другого класса, который должен быть уже определен. Например, если мы хотим перегрузить операцию вывода на экран элементов двумерного массива, определенного выше классом twomas, то нам будет нужен доступ к закрытым членам класса. Для обеспечения этого доступа в теле класса следует объявить прототип функции
friend ostream& operator << (ostream& o, twomas& d);
и определить операцию вывода с помощью внешней подпрограммы (функции):
ostream& operator << (ostream& o, twomas& d)
{
int i, j;
for(i = 1; i <= d.n; i++)
{
for(j = 1; j <= d.n; j++)
o << d(i, j) << ‘ ‘;
o << “n”;
}
return o;
}
Если класс содержит объекты другого класса в качестве полей, то его составным функциям необходим дополнительный доступ к закрытым членам этих полей. Например, в классе вектора, состоящего из n комплексных чисел
class Vectorc
{
Complex *z;
Public:
double norma();
};
составная функция norma(), возвращающая максимум абсолютных величин вещественных и мнимых компонент вектора, не имеет доступа к этим компонентам. Чтобы обеспечить этот доступ, в классе Complex следует указать функцию Vectorc::norma() как дружественную. Поскольку к моменту объявления составной функции класс
Vectorc должен быть определен, то следует указать перед определением класса Complex этот класс Vectorc как внешний (глобальный):
class Vectorc;
class Complex
{
double Re, Im;
friend double Vectorc::norma();
…
};
а затем определить класс Vectorc.
Существует возможность сделать доступными все члены класса А для каждой из составных функций класса В. Для реализации этой возможности достаточно класс B объявить дружественным для класса А. К моменту объявления класс B должен быть
определен или объявлен как внешний. Члены класса А не становятся доступными для дружественных функций класса B.
Пример. Определим класс графического окна, в которое будет выводиться график линейной функции. Линейная функция определяется как класс.
#include <graphics.h>
#include <conio.h>
class Wnd; // Прототип класса Wnd
// Класс — функция
class Func
{
// Закрытые элементы
double k, b; // y = kx + b
friend class Wnd; // Объявление дружественного класса
public: // Общедоступные элементы
Func(double k1, double b1=0): k(k1), b(b1) {} // Конструктор
};
// Класс окна
class Wnd
{
// Закрытые элементы
int xleft, xright, ytop, ybot; // Реальные координаты окна
double xmin, ymin, xmax, ymax; // Относительные координаты окна
public: // Общедоступные элементы
// Конструктор
Wnd(double x0, double y0, double x1, double y1,
int xl=0, int yt=0, int xr=639, int yb=479):
xmin(x0), ymin(y0), xmax(x1), ymax(y1),
xleft(xl), ytop(yt), xright(xr), ybot(yb) {}
Wnd& operator << (Func); // Перегрузка операции <<
};
// Перегрузка операции <<
Wnd& Wnd::operator << (Func f)
{
double xkof, ykof; // Коэффициенты перевода относительных
// координат в реальные
xkof = (xright-xleft)/(xmax-xmin);
ykof = (ybot-ytop)/(ymax-ymin);
rectangle(xleft, ytop, xright, ybot); // Рамка
line(xleft,
ytop+(ymax-ymin)*ykof/2,
xright,
ytop+(ymax-ymin)*ykof/2); // Ось х
line(xleft+(xmax-xmin)*xkof/2,
ytop,
xleft+(xmax-xmin)*xkof/2,
ybot); // Ось у
line((xright — xleft)/2 + xmin*xkof,
(ybot — ytop)/2 — (xmin*f.k+f.b)*ykof,
(xright — xleft)/2 + xmax*xkof,
(ybot — ytop)/2 — (xmax*f.k+f.b)*ykof); // Вывод функции
return (*this);
}
void main()
{
int gd=DETECT, gm;
Wnd w(-5, -3, 5, 3); // Определение окна
Func phi(1, 1); // Определение функции
initgraph(&gd, &gm, ""); // Инициализация графики
w<<phi; // Вывод функции phi в окно w
getch(); // Ожидание нажатия клавиши
closegraph(); // Закрытие графики
}
Результаты работы программы