что такое дружественная функция
Дружественные функции и классы в 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
Дружественные функции C++
Функция — это блок кода, который выполняет определенную задачу и предоставляет выходные данные. В основном он используется для устранения повторяющегося кода. В этом руководстве мы рассмотрим функцию друга в C ++ и объясним ее концепцию на рабочих примерах.
Что такое функция друга?
Дружественная функция — это функция, не являющаяся членом, которая может обращаться к закрытым и защищенным членам класса. «Друг» — это ключевое слово, используемое для обозначения того, что функция является другом класса. Это позволяет компилятору знать, что конкретная функция является другом данного класса. Тогда функция друга должна иметь доступ к закрытому и защищенному члену данного класса. Без ключевого слова friend внешняя функция, не являющаяся членом, может получить доступ только к открытым членам класса.
Ключевые особенности функции друга
Вот ключевые особенности функции друга:
Синтаксис дружественной функции
Вот синтаксис функции друга:
Пример функции друга
Теперь давайте рассмотрим пример программы, чтобы понять концепцию функции друга в C ++. В приведенном ниже примере программы у нас есть класс «Friend_Demo». Он имеет три разных типа данных: частные, защищенные и общедоступные.
Мы определили другую функцию, то есть «friendDemo_Func ()» вне области действия класса «Friend_Demo», и попытались получить доступ к членам (частным, защищенным и общедоступным) класса «Friend_Demo».
Но, как вы можете видеть в выводе ниже, когда мы компилируем программу, она выдает ошибки компиляции. Функция друга как раз решит эту проблему.
class Friend_Demo
<
private :
int i_private ;
protected :
int i_protected ;
public :
int i_public ;
> ;
void friendDemo_Func ( )
<
Friend_Demo fd ;
fd. i_private = 10 ;
fd. i_protected = 15 ;
fd. i_public = 20 ;
cout fd. i_private endl ;
cout fd. i_protected endl ;
cout fd. i_public endl ;
>
int main ( )
<
friendDemo_Func ( ) ;
В предыдущей программе мы получали ошибки компиляции при попытке доступа к закрытым, защищенным и общедоступным членам класса из функции, не являющейся членом. Это связано с тем, что функции, не являющейся членом, не разрешен доступ к закрытым и защищенным членам класса из-за пределов области действия класса.
Теперь, в этом примере, мы объявили функцию friendDemo_Func () как друга внутри области видимости класса, то есть «Friend_Demo»:
Мы создали объект, то есть «fd» класса «Friend_Demo» внутри функции «friendDemo_Func ()». Теперь мы можем получить доступ к закрытым, защищенным и общедоступным членам класса «Friend_Demo» с помощью оператора точки. Мы присвоили 10, 15 и 20 значениям i_private, i_protected и i_public соответственно.
Как вы можете видеть в выводе ниже, эта программа теперь компилируется и выполняется без каких-либо ошибок и выводит результат, как ожидалось.
class Friend_Demo
<
private :
int i_private ;
protected :
int i_protected ;
public :
int i_public ;
friend void friendDemo_Func ( ) ;
> ;
void friendDemo_Func ( )
<
Friend_Demo fd ;
fd. i_private = 10 ;
fd. i_protected = 15 ;
fd. i_public = 20 ;
cout fd. i_private endl ;
cout fd. i_protected endl ;
cout fd. i_public endl ;
>
int main ( )
<
friendDemo_Func ( ) ;
Заключение
В этой статье я объяснил концепцию функции друга в C ++. Я также показал два рабочих примера, чтобы объяснить, как функция друга ведет себя в C ++. Иногда функция друга может быть очень полезной в сложной среде программирования. Однако программисту следует быть осторожным, не злоупотребляя им и не ставя под угрозу его функции ООП.ции ООП.
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) не может иметь дружественных функций, дружественных классов или дружественных интерфейсов.
Последствия дружественных отношений
Встроенные определения дружественных элементов
Дружественные функции могут быть определены (при наличии тела функции) внутри объявлений класса. Эти функции являются встраиваемыми, и как встраиваемые функции членов они ведут себя так, как если бы они были определены сразу после просмотра всех членов класса, но до закрытия области класса (конец объявления класса). Дружественные функции, определенные внутри объявлений класса, находятся в области включающего класса.
Урок №126. Дружественные функции и классы
Обновл. 13 Сен 2021 |
На этом уроке мы рассмотрим использование дружественных функций и дружественных классов в языке С++.
Проблема
На предыдущих уроках мы говорили о том, что данные вашего класса должны быть private. Однако может возникнуть ситуация, когда у вас есть класс и функция, которая работает с этим классом, но которая не находится в его теле. Например, есть класс, в котором хранятся данные, и функция (или другой класс), которая выводит эти данные на экран. Хотя код класса и код функции вывода разделены (для упрощения поддержки кода), код функции вывода тесно связан с данными класса. Следовательно, сделав члены класса private, мы желаемого эффекта не добьёмся.
В таких ситуациях есть два варианта:
Сделать открытыми методы класса и через них функция будет взаимодействовать с классом. Однако здесь есть несколько нюансов. Во-первых, эти открытые методы нужно будет определить, на что потребуется время, и они будут загромождать интерфейс класса. Во-вторых, в классе нужно будет открыть методы, которые не всегда должны быть открытыми и предоставляющими доступ извне.
Использовать дружественные классы и дружественные функции, с помощью которых можно будет предоставить функции вывода доступ к закрытым данным класса. Это позволит функции вывода напрямую обращаться ко всем закрытым переменным-членам и методам класса, сохраняя при этом закрытый доступ к данным класса для всех остальных функций вне тела класса! На этом уроке мы рассмотрим, как это делается.
Дружественные функции
Дружественная функция — это функция, которая имеет доступ к закрытым членам класса, как если бы она сама была членом этого класса. Во всех других отношениях дружественная функция является обычной функцией. Ею может быть, как обычная функция, так и метод другого класса. Для объявления дружественной функции используется ключевое слово friend перед прототипом функции, которую вы хотите сделать дружественной классу. Неважно, объявляете ли вы её в public- или в private-зоне класса. Например:
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).
Точки и векторы часто используются в компьютерной графике (точки представляют вершины фигуры, а векторы представляют движение фигуры).
Учитывая следующую программу: