Шаг 13.
Дружественные функции

    На этом шаге мы начнем изучение дружественных функций и их возможностей.

    Дружественной функцией класса называется функция, которая, не являясь его компонентом, имеет доступ к его защищенным и собственным компонентам. Функция не может стать другом класса "без его согласия". Для получения прав друга функция должна быть описана в теле класса со спецификатором friend. Именно при наличии такого описания класс предоставляет функции права доступа к защищенным и собственным компонентам. Пример класса с дружественной функцией:

//OOР13_01.СРР - класс с дружественной функцией.
#include <conio.h>   // Для консольных функций в текстовом режиме.
// Класс - "символ в заданной позиции экрана": 
class charlocus {    
	int x, y;   // Координаты знакоместа на экране дисплея.
	// Значение символа, связанного со знакоместом:
	char cc;
	// Прототип дружественной функции для замены символа:
	friend void friend_put(charlocus *, char);
  public:
	charlocus(int xi, int yi, char ci) // Конструктор.
		{ x = xi; y = yi; cc = ci; }
	void display (void)  // Вывести символ на экран.
		{ gotoxy(x,y); putch(cc); }
};
// Дружественная функция замены символа в конкретном
// объекте:
void friend_put(charlocus *p, char c)
  { p->cc = c; }
void main (void)
{ charlocus D(20,4,'d');  // Создать объект.
  charlocus S(10,10,'s'); // Создать объект.
  D.display (); getch();
  S.display (); getch();
  friend_put(&D,'*'); D.display(); getch();
  friend_put(&S,'#'); S.display(); getch();
}
Текст этой программы можно взять здесь.

    Программа последовательно выводит на экран d (в позицию 20, 4), s (в позицию 10, 10), * (в позицию 20, 4), # (в позицию 10, 10).

    Для работы с экраном в текстовом режиме использованы две функции из библиотеки Turbo С. Их прототипы находятся в заголовочном файле conio.h, где специфицированы так называемые "консольные" функции ввода-вывода. В других компиляторах языка C++ эти функции могут быть определены иначе.

    Прокомментируем приведенную программу.

    Функция friend_put() описана в классе charlocus как дружественная и определена как обычная глобальная функция (вне класса, без указания его имени, без операции :: и без спецификатора friend). Как дружественная она получает доступ к собственным данным класса и изменяет значение символа того объекта, адрес которого будет передан ей как значение первого параметра.

    Выполнение основной программы очевидно. Создаются два объекта D и S, для которых определяются координаты мест на экране и символы (d, s). Затем общедоступная функция класса charlocus::display() выводит символы в указанные позиции экрана. Функция friend_put заменяет символы объектов, что демонстрирует повторный вывод на экран.

    Отметим особенности дружественных функций.

  1. Дружественная функция при вызове не получает указателя this. Объекты классов должны передаваться дружественной функции только явно через аппарат параметров.
  2. При вызове дружественной функции нельзя использовать операции выбора:
        имя_объекта.имя_функции
                 и
        указатель_на_объект  -> имя_функции
    
    Все это связано с тем фактом, что дружественная функция не является компонентом класса.
  3. Именно поэтому на дружественную функцию не распространяется и действие спецификаторов доступа (public, protected, private). Место размещения прототипа дружественной функции внутри определения класса безразлично. Права доступа дружественной функции не изменяются и не зависят от спецификаторов доступа. В приведенном примере описание функции friend_put() помещено в разделе, который по умолчанию имеет статус доступа private.

    Итак, дружественная функция:

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




Предыдущий шаг Содержание Следующий шаг