Область друзей в C++
Если у меня есть три класса, A, B, C. A и B - друзья (двунаправленные). Также B и C являются друзьями (двунаправленно). A имеет указатель на B, а B имеет указатель на C. Почему A не может получить доступ к личным данным C через указатель?
Просто для пояснения: это чисто теоретический вопрос о языке C++, а не вопрос о совете по дизайну.
5 ответов
Дружба в C++ не транзитивна:
Джон мой друг, и он может использовать мое беспроводное соединение в любое время (я ему доверяю).
Тем не менее, друг Джона Тим - бред, и хотя Джон - мой друг, я не включаю Тима в друзья, и поэтому я не позволяю ему использовать мое беспроводное соединение.
Дружба НЕ наследуется
Также дети Джона - кучка хулиганов, поэтому я не доверяю им, они точно не мои друзья, и не мои собственные дети, которым я доверяю, насколько я могу их бросить.
Хотя наши дети не могут напрямую получить доступ к беспроводной связи, они могут получить к ней доступ, если они пройдут через нас. Таким образом, дети Джона могут получить доступ к моей беспроводной связи, если они получат к ней доступ через Джона (то есть они находятся под наблюдением и защитой Джона)
Также дружба не симметрична.
У Джона есть государственная работа, поэтому ему, к сожалению, запрещено доверять кому-либо, особенно когда речь идет о беспроводной связи.
Ты всегда твой лучший друг.
Это позволяет такие вещи, как конструкторы копирования, где вы можете получить доступ к закрытому члену другого объекта, даже если нет реального доступа.
Таким образом, я также автоматически дружу со всеми своими клонами:-), поскольку они - просто другие экземпляры меня.
Дружба в 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++
Потому что в C++ дружба не является переходным свойством. На самом деле этого следует избегать всякий раз, когда это возможно, потому что это вносит сложности в систему.
Представьте себе, что B - это класс-посредник, а A и C - это компоненты, которыми нужно управлять. Вы действительно думаете, что имеет смысл, что кнопка должна иметь доступ к реализации флажка?
Кстати, я не вижу, где находится "иерархия" вашего заголовка в случае, который вы спрашиваете.
Это все хорошо подытожено здесь:
What does it mean that "friendship isn't inherited, transitive, or reciprocal"?
->
Это означает, что классы, полученные из класса друзей, не становятся автоматически друзьями (вы доверяете детям своих друзей?), Друг друга автоматически не становится другом (вы доверяете друзьям своих друзей?) и что класс, объявляющий другой класс "другом", автоматически не становится другом этого класса (доверяете ли вы любому, кто называет вас другом?).
от