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

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

17 голосов
/ 13 января 2009

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

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

Ответы [ 5 ]

132 голосов
/ 13 января 2009

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

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

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

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

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

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

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

Ты всегда твой лучший друг.

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

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

24 голосов
/ 13 января 2009

Дружба в 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. Если добавление метода установки и получения в класс предоставляет информацию, не предназначенную для раскрытия, вам следует подумать о друзьях, если вы не могу найти ваш дизайн, будучи дефектным (использование друга действительно. Это не признак плохого дизайна). Если вы можете добавить сеттер и геттер без ущерба для интерфейса, то вам следует избегать дружбы с другими классами. Обратите внимание, что вложенный класс всегда является другом класса вложенности. Таким образом, вложенный класс может видеть ряды вложенного класса.

3 голосов
/ 13 января 2009

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

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

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

3 голосов
/ 13 января 2009

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

2 голосов
/ 06 февраля 2014

Здесь все хорошо подытожено:

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

->

Это означает, что классы, полученные из классов друзей, не автоматически становиться друзьями (доверяете ли вы детям своих друзей?), друг друга автоматически не становится другом доверять друзьям своих друзей?) а что за класс декларирует другой класс как «друг» автоматически не становится другом этот класс (ты доверяешь любому, кто называет тебя другом?).

от

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

...