friend (C++)
В некоторых случаях удобнее предоставлять доступ на уровне членов к функциям, которые не являются членами класса или всем членам в отдельном классе. Только реализатор класса может объявить, что является для него дружественным элементом. Функция или класс не могут объявить себя дружественным элементом для любого класса. В определении класса используйте friend ключевое слово и имя функции, не являющейся членом, или другой класс, чтобы предоставить ему доступ к закрытым и защищенным членам класса. В определении шаблона параметр типа может быть объявлен дружественным.
Синтаксис
Объявления дружественных элементов
При объявлении дружественной функции, которая не была объявлена ранее, эта функция экспортируется во включающую область вне класса.
Функции, объявленные в дружественном объявлении, обрабатываются так, как если бы они были объявлены с помощью extern ключевого слова. Дополнительные сведения см. в разделе extern.
Хотя функции с глобальной областью действия могут быть объявлены как дружественные до объявления своих прототипов, функции-члены не могут быть объявлены как дружественные функции до полного объявления их класса. В следующем коде показано, почему при этом возникает ошибка.
Начиная с C++ 11, существует две формы дружественных объявлений для класса:
Первая форма представляет новый класс F, если в самом внутреннем пространстве имен не найден существующий класс с таким именем. C++ 11. во второй форме не представлен новый класс. его можно использовать, если класс уже объявлен и должен использоваться при объявлении параметра типа шаблона или typedef как дружественного.
В следующем примере friend F ссылается на F класс, объявленный вне области видимости NS.
Используйте friend F для объявления параметра шаблона в качестве дружественного:
Чтобы объявить два класса как дружественные друг другу, весь второй класс должен быть указан как дружественный для первого класса. Причина такого ограничения заключается в том, что компилятор получает достаточные сведения для объявления отдельных дружественных функций только в момент объявления второго класса.
Хотя весь второй класс должен быть дружественным для первого класса, можно выбрать, какие функции первого класса будут дружественными для второго класса.
дружественные функции
friend Функция — это функция, которая не является членом класса, но имеет доступ к закрытым и защищенным членам класса. Дружественные функции не считаются членами класса; это обычные внешние функции с особыми правами доступа. Друзья не находятся в области класса и не вызываются с помощью операторов выбора членов (. и- ), если они не являются членами другого класса. friend Функция объявляется классом, который предоставляет доступ. friend Объявление можно поместить в любое место объявления класса. На него не влияют ключевые слова управления доступом.
Члены класса как дружественные элементы
Функции-члены класса могут быть объявлены в других классах как дружественные. Рассмотрим следующий пример.
Класс friend — это класс, все функций-члены которого являются дружественными функциями класса, то есть функции-члены которого имеют доступ к закрытым и защищенным членам другого класса. Предположим, что в классе friend было следующее объявление B :
Управляемый тип (в C++/CLI) не может иметь дружественных функций, дружественных классов или дружественных интерфейсов.

Последствия дружественных отношений
Встроенные определения дружественных элементов
Дружественные функции могут быть определены (при наличии тела функции) внутри объявлений класса. Эти функции являются встраиваемыми, и как встраиваемые функции членов они ведут себя так, как если бы они были определены сразу после просмотра всех членов класса, но до закрытия области класса (конец объявления класса). Дружественные функции, определенные внутри объявлений класса, находятся в области включающего класса.
Дружественные функции и классы в C++
В этом руководстве мы научимся создавать дружественные функции и классы на C++ с помощью примеров. Скрытие данных – фундаментальная концепция объектно-ориентированного программирования, которая ограничивает доступ частных членов извне класса. Точно так же защищенные члены могут быть доступны только производным классам и недоступны извне. Например:
Однако в С++ есть функция, называемая дружественной, которая нарушает это правило и позволяет нам получать доступ к функциям-членам извне класса.
Точно так же есть дружественный класс, о котором мы узнаем позже в этом руководстве.
Что такое дружественная функция в C++?
Дружественная функция в C++ может получить доступ к личным и защищенным данным класса. Мы объявляем функцию, используя ключевое слово friend внутри тела класса.
Пример 1: работа функции
Здесь addFive() – это дружественная функция, которая может обращаться как к частным, так и к публичным элементам данных.
Хотя этот пример дает нам представление о концепции функции, он не показывает какого-либо значимого использования.
Более осмысленное использование будет работать с объектами двух разных классов. В этом случае функция friend может оказаться очень полезной.
Пример 2: добавление членов двух разных классов
В этой программе ClassA и ClassB объявили add(), как дружественную функцию. Таким образом, эта функция может получить доступ к приватным данным обоих классов.
Здесь следует отметить одну вещь: функция внутри ClassA использует ClassB. Однако мы еще не определили ClassB.
Чтобы это работало, нам нужно предварительное объявление ClassB в нашей программе.
Дружественный класс в C++
Мы также можем использовать Friend Class (дружественный класс) в С++, используя ключевое слово friend. Например:
Когда класс объявляется дружественным классом, все функции-члены дружественного класса становятся дружественными функциями.
Поскольку classB является дружественным классом, мы можем получить доступ ко всем членам classA изнутри classB.
Однако мы не можем получить доступ к членам ClassB изнутри classA. Это потому, что дружеские отношения в C++ только предоставляются, но не принимаются.
Пример 3
Урок №126. Дружественные функции и классы
Обновл. 13 Сен 2021 |
На этом уроке мы рассмотрим использование дружественных функций и дружественных классов в языке С++.
Проблема
На предыдущих уроках мы говорили о том, что данные вашего класса должны быть private. Однако может возникнуть ситуация, когда у вас есть класс и функция, которая работает с этим классом, но которая не находится в его теле. Например, есть класс, в котором хранятся данные, и функция (или другой класс), которая выводит эти данные на экран. Хотя код класса и код функции вывода разделены (для упрощения поддержки кода), код функции вывода тесно связан с данными класса. Следовательно, сделав члены класса private, мы желаемого эффекта не добьёмся.
В таких ситуациях есть два варианта:
Сделать открытыми методы класса и через них функция будет взаимодействовать с классом. Однако здесь есть несколько нюансов. Во-первых, эти открытые методы нужно будет определить, на что потребуется время, и они будут загромождать интерфейс класса. Во-вторых, в классе нужно будет открыть методы, которые не всегда должны быть открытыми и предоставляющими доступ извне.
Использовать дружественные классы и дружественные функции, с помощью которых можно будет предоставить функции вывода доступ к закрытым данным класса. Это позволит функции вывода напрямую обращаться ко всем закрытым переменным-членам и методам класса, сохраняя при этом закрытый доступ к данным класса для всех остальных функций вне тела класса! На этом уроке мы рассмотрим, как это делается.
Дружественные функции
Дружественная функция — это функция, которая имеет доступ к закрытым членам класса, как если бы она сама была членом этого класса. Во всех других отношениях дружественная функция является обычной функцией. Ею может быть, как обычная функция, так и метод другого класса. Для объявления дружественной функции используется ключевое слово friend перед прототипом функции, которую вы хотите сделать дружественной классу. Неважно, объявляете ли вы её в public- или в private-зоне класса. Например:
BestProg
Содержание
Поиск на других ресурсах:
1. Для чего используются так называемые «друзья» класса?
Бывают случаи, когда для заданного класса нужно объявить другой класс или функцию, которые должны иметь неограниченный доступ к внутренним переменным и методам класса. Такая необходимость возникает из сути решаемой задачи.
Таким образом, «дружественный» класс или функция дополняют функционал класса в котором они объявлены как «дружественные».
2. Какая общая форма объявления «дружественного» класса? Ключевое слово friend
3. Какая общая форма объявления «дружественной» функции к некоторому классу?
Если нужно объявить «дружественную» функцию в некотором классе, то общий вид такого объявления следующий:
4. В каком месте объявления класса можно объявлять «дружественный» класс или функцию?
Объявлять «дружественный» класс или функцию к заданному классу можно в любом месте или разделе класса в пределах его объявления (между фигурными скобками < >).
5. Сколько «дружественных» функций и «дружественных» классов можно объявлять в теле класса?
6. Как получить объект нужного класса в «дружественной» функции, чтобы иметь доступ ко всем его членам? Пример
Чтобы получить объект нужного класса в функции целесообразно передать в эту функцию ссылку (или указатель) на объект этого класса.
Объявление класса CMyClass и «дружественной» функции в классе имеет следующий вид:
Реализация «дружественной» функции FriendFun() :
7. Пример объявления класса, который есть «дружественным» к другому классу
Листинг классов Number и RangeNum имеет вид:
Использование классов в другом программном коде
Если в классе Number в объявлении «дружественного» класса RangeNum
8. Пример объявления функции, которая есть «дружественной» к другому классу
Листинг приложения типа « Win32 Console Application » следующий:
Как видно из вышеприведенного кода, «дружественные» функции получают входным параметром ссылку или указатель на объект класса, к членам данных и методам которого они имеют неограниченный доступ.
12.15 – Дружественные функции и классы
Большую часть этой главы мы проповедовали достоинства сохранения скрытости ваших данных. Однако иногда вы можете столкнуться с ситуациями, когда обнаружите, что у вас есть классы и функции вне этих классов, которые должны очень тесно работать друг с другом. Например, у вас может быть класс, в котором хранятся данные, и функция (или другой класс), которая отображает эти данные на экране. Хотя класс хранилища и код отображения были разделены для упрощения поддержки, код отображения на самом деле тесно связан с деталями класса хранилища. Следовательно, скрытие сведений о классах хранения от кода отображения не дает особой выгоды.
В подобных ситуациях есть два варианта:
Дружественные функции
Дружественная функция – это функция, которая может получить доступ к закрытым членам класса, как если бы она была членом этого класса. Во всем остальном дружественная функция похожа на обычную функцию. Дружественная функция может быть либо обычной функцией, либо функцией-членом другого класса. Чтобы объявить дружественную функцию, просто используйте ключевое слово friend перед прототипом функции, которую вы хотите сделать другом класса. Не имеет значения, объявляете ли вы дружественную функцию в закрытом или открытом разделе класса.
Вот пример использования дружественной функции:
Вот еще один пример:
Хотя оба приведенных выше примера довольно надуманы, последний пример очень похож на случаи, с которыми мы столкнемся позже, когда будем обсуждать перегрузку операторов!
Несколько друзей
Функция может быть другом для более чем одного класса одновременно. Например, рассмотрим следующий пример:
В этом примере стоит отметить две вещи. Во-первых, поскольку printWeather является другом обоих классов, она может получить доступ к закрытым данным из объектов обоих классов. Во-вторых, обратите внимание на следующую строку в верхней части примера:
Дружественные классы
Также целый класс можно сделать другом другого класса. Это дает всем членам дружественного класса доступ к закрытым членам другого класса. Вот пример:
Будьте осторожны при использовании дружественных функций и классов, потому что это позволяет дружественной функции или классу нарушать инкапсуляцию. Если детали реализации класса изменятся, то детали реализации друга также должны будут быть изменены. Следовательно, ограничьте использование дружественных функций и классов до минимума.
Дружественные функции-члены
Вместо того чтобы делать другом весь класс, вы можете сделать другом только одну функцию-член. Это делается аналогично тому, как сделать дружественной обычную функцию, за исключением использования имени функции-члена с включенным префиксом ИмяКласса:: (например, Display::displayItem ).
Однако на самом деле это может быть немного сложнее, чем ожидалось. Давайте, преобразуем предыдущий пример, чтобы сделать Display::displayItem дружественной функцией-членом. Вы можете попробовать сделать что-то вроде этого:
Вот как это выглядит:
Резюме
Дружественная функция или класс – это функция или класс, которые могут получить доступ к закрытым членам другого класса, как если бы они были членами этого класса. Это позволяет дружественной функции или классу тесно работать с другим классом, не заставляя другой класс открывать свои закрытые члены (например, через функции доступа).
Объявление друзьями обычно используется при определении перегруженных операторов (о которых мы поговорим в следующей главе) или, реже, когда два или более класса должны тесно взаимодействовать друг с другом.
Обратите внимание, что для того, чтобы сделать конкретную функцию-член другом, необходимо сначала увидеть полное определение класса функции-члена.
Небольшой тест
Вопрос 1
В геометрии точка – это позиция в пространстве. Мы можем определить точку в трехмерном пространстве как набор координат x, y и z. Например, Point(2.0, 1.0, 0.0) будет точкой в пространстве с координатами x = 2.0, y = 1.0 и z = 0.0.
В физике вектор – это величина, которая имеет величину (длину) и направление (но не положение). Мы можем определить вектор в трехмерном пространстве как значения x, y и z, представляющие направление вектора вдоль осей x, y и z (длина может быть получена из них). Например, Vector(2.0, 0.0, 0.0) будет вектором, представляющим направление вдоль (только) положительной оси x, с длиной 2.0.
Вектор можно применить к точке, чтобы переместить точку в новое положение. Это делается путем добавления направления вектора к положению точки, чтобы получить новое положение. Например, Point(2.0, 1.0, 0.0) + Vector(2.0, 0.0, 0.0) даст точку (4.0, 1.0, 0.0).
Точки и векторы часто используются в компьютерной графике (точки представляют вершины фигуры, а векторы представляют движение фигуры).
Учитывая следующую программу:



