Мы уже познакомились с основным правилом ООП - данные(внутренние переменные) объекта защищены от воздействий из вне и доступ к ним можно получить только с помощью методов(функций) объекта. Но бывают такие случаи, когда нам необходимо получить доступ к данным объекта не используя его интерфейс. Зачем это может понадобиться ? Как я уже как-то упоминал, при доступе к внутренним переменным объекта через его методы уменьшается эффективность работы за счет затрат на вызов метода. В большинстве случаев нам это не критично, но не всегда. В некоторых случаях это может играть существенную роль. Конечно, можно добавить новый метод к классу для получения прямого доступа к внутренним переменным. Однако, в большинстве случаев, интерфейс объекта (методы) спланирован для выполнения определенного круга операций, и наша функция может оказаться как бы ни к месту. А если хуже того, нам необходимо получить прямой доступ к внутренним данным двух разных объектов ? Возникает проблема. Именно для решения подобных задач и существует возможность описание функции, метода другого класса или даже класса как дружественного(friend).
Итак, как же работает этот механизм.
Для описания дружественной тому или иному классу функции(метода или класса) необходимо в описании этого класса объявить (описать) дружественную функцию с указанием ключевого слова friend. Если функция дружественна нескольким классам, то надо добавить это описание во все классы, к внутренним данным которых производим обращение. В большинстве языков ООП не имеет различия в какой раздел описания класса(publuc, protected или private) вставлено описание дружественной функции.
Но возникает такой вопрос: А как же наша хваленая защищенность данных, если можно получить доступ к данным напрямую ?
Но оказывается, что с точки зрения применимости механизма инкапсуляции, защищенность данных сохраняется, поскольку полностью исключается всякая возможность доступа к данным так, чтобы объект не был осведомлен об этом.
А теперь приведу несколько примеров использования дружественных функций(и не только) в языке С++.
// Описание класса A class A { //... void z(); // Описание функции z класса A }; // Описание класса B class B { //... friend void A::z(); // Описание функции z класса A как дружественной // классу B, т.е. из функции z класса A можно // получить доступ к внутренним переменным класса B }; // Описание класса C class C { //... friend class A; // Описание класса A как дружественного классу C, // все функции класса A будут дружественны классу C и // из любой функции класса A можно получить доступ к // внутренним переменным класса C }