Область друзей в C++

Если у меня три класса, A, B, C. A и B - друзья (двунаправленно). Кроме того, B и C друзья (двунаправленно). У A есть указатель на B, а у B есть указатель на C. Почему A не может получить доступ к личным данным C через указатель?

Просто для пояснения: это чисто теоретический вопрос языка C++, а не вопрос совета по дизайну.

Что интересно, это легко обойти, добавив функции «getter» для получения указателей. (Получатель B вызова A, который вызывает получатель C.)

Marcin 13.01.2009 01:32

Дружественные классы чаще всего можно устранить, немного изменив дизайн. Это как бы вредит принципам объектно-ориентированного проектирования и увеличивает взаимосвязь с ИМО.

Perpetualcoder 13.01.2009 01:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
2
8 746
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Дружба в C++ не транзитивна:

(A is friend of B) and (B is friend of C) does not mean (A is friend of C)

Кроме того, дружба не симметрична.

(A is friend of B) does not mean (B is friend of A) 

Вы должны явно указать, что A является другом C, чтобы иметь возможность получить доступ к частным данным C изнутри A. Если добавление установщика и получателя к классу раскрывает информацию, не предназначенную для раскрытия, вам следует подумать о друзьях, если вы не можете обнаружите, что ваш дизайн неисправен (использование друга допустимо. Это не признак плохого дизайна). Если вы можете добавить сеттер и получатель, не разрушая интерфейс, вам следует избегать дружбы с другими классами. Обратите внимание, что вложенный класс всегда является другом вложенного класса. Таким образом, вложенный класс может видеть частные лица вложенного класса.

Я только что нашел эту статью, пока ждал ответов. Он довольно хорошо отвечает на мой вопрос: Область друзей в C++

Кратко опишите те части статьи, которые, по вашему мнению, решают вашу проблему.

Benjamin Gruenbaum 22.06.2013 23:48

Потому что в C++ дружба не является переходным свойством. На самом деле этого следует избегать, когда это возможно, потому что это усложняет систему.

Представьте, что B - это класс-посредник, а A и C - это компоненты, которыми нужно управлять. Неужели вы думаете, что имеет смысл, что кнопка должна иметь доступ к реализации флажка?

Между прочим, я не понимаю, где находится «иерархия» вашего заголовка в том случае, если вы спрашиваете.

Ответ принят как подходящий

Дружба в C++ не транзитивна:

Джон - мой друг, и он может использовать мое беспроводное соединение в любое время (я ему доверяю). Друг Джона Тим, тем не менее, расточитель, и хотя Джон - мой друг, я не считаю Тима своим другом, и поэтому я не позволяю ему использовать мое беспроводное соединение.

Дружба НЕ передается по наследству

Кроме того, дети Джона - кучка хулиганов, поэтому я им не доверяю, либо они определенно не мои друзья, либо мои собственные дети, которым я доверяю, насколько я могу их бросить.

Хотя наши дети не могут напрямую получить доступ к беспроводной сети, они могут получить к ней доступ, если будут проходить через нас. Таким образом, дети Джона могут получить доступ к моей беспроводной сети, если они получают доступ к ней через Джона (т.е. они находятся под наблюдением и защищенный Джоном).

Кроме того, дружба не симметрична.

У Джона правительственная работа, поэтому ему, к сожалению, нельзя доверять никому, особенно когда дело касается беспроводной связи.

Вы всегда сами себе лучший друг.

Это позволяет использовать такие вещи, как конструкторы копирования, где вы можете получить доступ к закрытому члену другого объекта, даже если нет реального доступа.

Так что я автоматически дружу со всеми моими клонами :-), поскольку они всего лишь другие экземпляры меня.

Ха! Я ни за что не забуду эту концепцию после прочтения вашего ответа :)

Marcin 13.01.2009 18:14

любой пример для последнего? [я новичок] помогите разобраться [конструктор копирования]

Dineshkumar 03.07.2013 20:59

@Dineshkumar: Взгляните на любой конструктор копирования. К копируемому объекту напрямую обращается объект, созданный копией (даже если эти члены являются частными).

Martin York 03.07.2013 23:12

Все это хорошо подытожено здесь:

What does it mean that "friendship isn't inherited, transitive, or reciprocal"?

->

It means that classes derived from a friend class don't automatically become friends (do you trust the kids of your friends?), a friend of a friend doesn't automatically become a friend (do you trust the friends of your friends?), and that a class declaring another class as "friend" doesn't automatically become a friend of that class (do you trust anyone who calls you a friend?).

из

http://yosefk.com/c++fqa/friend.html#fqa-14.4

Другие вопросы по теме