Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Вариант_№32.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
363.52 Кб
Скачать

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

Одним из важных принципов С++ является защита данных от несанкционированного использования с помощью режимов доступа к элементам класса. Обычно доступ к собственным (private) элементам класса ограничивается методами этого класса. Однако возникают ситуации, когда необходимо, чтобы к закрытым элементам данных класса имела доступ функция, не принадлежащая этому классу и даже из другого класса. Это можно сделать, объявив эту функцию с помощью ключевого слова friend (друг) как дружественную функцию (friend function). Например,

class X

{ int n;

public:

friend void fr (void);

};

Функция fr может обращаться к элементу n.

Обычное объявление функции-элемента гарантирует три логически разные вещи:

  • функция имеет право доступа к закрытой части объявления класса;

  • функция находится в области видимости класса;

  • функция должна вызываться для объекта класса (имеется указатель this).

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

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

Пример 50.

Представим программу использования функции-друга для двух классов (Box, Line). Она должна изобразить на экране цветные прямоугольники и линии, сравнивая попарно их цвета (color) функцией-другом samecolor(). Если цвета совпадают, выдается сообщение Same color, иначе Different color.

#include<iostream.h>

#include<conio.h>

class Line; // предварительное объявление класса Line

class Box // класс "прямоугольник"

{ int color; // цвет рамки

int upx, upy; // координаты левого верхнего угла

int lowx, lowy; // координаты правого нижнего угла

public:

friend int samecolor (Line l, Box b); // функция-друг

void setcolor (int c); // цвет

void definebox (int x1, int y1, int x2, int y2); // координаты

void showbox (); // вывод на экран

};

class Line // класс "линия"

{ int color; // цвет линии

int x0, y0; // координаты начала линии

int len; // длина линии

public: // прототипы функций:

friend int samecolor (Line l, Box b); // функция-друг

void setcolor (int c); // цвет рамки

void defineline (int x, int y, int l); // координаты и длина линии

void showline (); // вывод линии

};

// Описание методов класса Box:

void Box :: setcolor (int c) // установка цвета

{ color = c;

}

void Box :: definebox (int x1, int y1, int x2, int y2) // координаты

{ upx = x1; upy = y1; lowx = x2; lowy = y2;

}

void Box :: showbox () // метод вывода прямоугольника

{ window(upx, upy,lowx, lowy); // координаты окна

textbackground (color); // установка цвета фона

clrscr(); // чистка окна

textbackground (BLACK); // цвет фона

window (1, 1, 80, 25); // окно экрана

}

// Описание методов класса Line:

void Line :: setcolor (int c) // установка цвета линии

{ color = c;

}

void Line :: defineline (int x, int y, int l) // определение линии

{ x0 = x; y0 = y; len = l; // координаты и длина линии

}

void Line :: showline () // метод вывода линии

{ textcolor (color); // цвет линии

gotoxy (x0, y0); // начало линии

for (int k=0; k<len; k++) // цикл вывода линии

cprintf("%c", '-');

textcolor (WHITE); // смена цвета линии

}

// Описание функции-друга:

int samecolor (Line l, Box b)

{ if (l.color == b.cololr) // если цвета линии и окна одинаковы, то

return 1; // возврат 1, иначе

return 0; // возврат 0

}

void main () // главная функция

{ Line l; // создание объекта линии

Box b; // создание объекта прямоугольника

textbackground (BLACK); // установка цвета фона

clrscr (); // чистка экрана

b.definebox (5, 5, 25, 10); // задание координат прямоугольника

b.setcolor (RED); // цвет прямоугольника

l.defineline (5, 15, 30); // задание координат и длины линии

l.setcolor (BLUE); // цвет линии

b.showbox (); // вывод прямоугольника

l.showline (); // вывод линии

gotoxy (1,1); // координаты курсора

if (samecolor (l, b)) // если цвета линии и окна одинаковы

cputs ("Same colors\n"); // сообщение:"Цвета одинаковы"

else cputs ("Different colors\n"); // иначе "Цвета различны"

getch (); // задержка экрана

}

Комментарии к программе.

В программе дано предварительное объявление класса Line, похожее на прототип (class Line;), которое используется в классе Box, до того как опреде­лен класс Line, поэтому необходимо сделать такое уведомление.

Дружественной может быть не только внешняя функция, как в примере, но и метод другого класса. Например:

class X { // …

int* next();

};

class Y

{ friend int* X:: next();

// …

};

В примере, рассмотренном выше, можно было бы объявить функцию samecolor методом класса Box, изменив его описание:

class Box

{ ...

public:

int samecolor ( Line l); // метод класса Box

...

};

В классе Line необходимо объявить функцию-друга:

class Line

{ ...

public:

friend int Box::samecolor (Line l); // функция-друг

...

};

В классе Line использовано полное имя функции Box::samecolor(). Кро­ме того, можно не указывать в качестве аргумента объект класса Box. Новая функция-друг Box::samecolor() примет вид:

int Box::samecolor ( Line l )

{ if (l.color == color) // используется указатель this -> color

return 1;

return 0;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]