Является ли это хорошей идеей или нет, вот объяснение причины ее сбоя:
Компилятор использует несколько различных этапов обработки, чтобы выяснить, что говорит ваша программа.Причина, по которой класс B
не компилируется, заключается в том, что происходящий сбой происходит до того, как будет замечен friend
.Позвольте мне объяснить:
Когда компилятор пытается выяснить, что означает swap
, он выполняет поиск по имени.Он использует определенные правила, которые указывают, где он должен выглядеть.Это упрощено, но в основном сначала выполняется поиск символов, определенных в локальной области видимости, затем в области видимости класса, а затем во вложенных областях (пространства имен и т. Д.).Он находит тот, определенный в области видимости класса, и перестает искать.swap
не принимает эти 2 параметра, поэтому компиляция не удалась.
Объявление friend
, которое позволяет свободной функции получать доступ к внутренним компонентам B
, действует как дополнительное объявление дляswap
функция, которую вы объявили в глобальном пространстве имен.Эти объявления будут рассмотрены компилятором, если он дойдет до точки поиска имени, где он рассматривает функции в глобальном пространстве имен.В классе B
компилятор уже прекратил обработку, прежде чем он достигнет этой стадии.(И объявление friend
было бы необходимо на более позднем этапе, когда компилятор работает над компиляцией версии функции swap
, которая работает с B
объектами и хочет выяснить, "в этой функции, называемойswap
, который может принимать эти 2 параметра; могу ли я получить доступ к внутренним элементам B
? ")
В классе A
вы используете другое имя.Фаза поиска имени не будет успешной, пока она не найдет вашу бесплатную функцию swap
.В классе C
вы дали конкретные инструкции по поиску имен: «эй, когда вы ищите swap
, посмотрите в области глобальных пространств имен и игнорируйте те, что в локальной и области классов, которые выможет найти. "
(Примечание: описание поиска имени и friend
обновлено после комментария @ PeteBecker.)