Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 49
Текст из файла (страница 49)
*/ ) )тл() (/* ... */) ) Так как мы не планируем делать имя Мте доступным вне локального контекста, выбор имени становится определенной обузой, к тому же отягощенной возможностью конфликта с другими глобальными именами. В этом случае имя пространства имен можно просто опустить: ()1пс1иае "Йеааег. Й" патеврасе ( 1пг а; гоЫ/() (/* ... */) )пгл() (/* ... */) Доступ к членам неименованного пространства имен (иппатег1 патезросе) осуществляется в локальном контексте без квалификации, так что предыдущее объявление эквивалентно следующему объявлению патеврасе ЗЗЗ ( 1пг а; гоЫ/() (/* ...
*/) 1пгл() (/* ... */) ) ияпл патеврасе ЗЗЗ) плюс соответствующая директива из)пл, а З 3 3 — некоторое уникальное для текущей области видимости имя. 8.2. Пространства имен 233 Неименованные пространства имен в разных единицах компиляции разные по определению, так что, как и задумано, невозможно обратиться к члену неименованного пространства имен из другой единицы компиляции.
8.2.6. Поиск имен Чаще всего функция с аргументом типа Т определяется в том же пространстве имен, что и тип Т. Поэтому, если функцию не удается найти в контексте, где она используется, поиск продолжается в пространстве имен ее аргументов. Например: патеярасе Слгопо ( с!аяя Вате( /* ... */ ); Ьоо! орега<ог== (сопя! Ваяея, сопя( язд:: язг/пяа ); яз4::я!г!пя/оста!(сопя! Вагез); //выдать строковое представление // ... ) чоЫТ(СЪгопо::Ва!е И, т! !) ( яяа::язгяпя я =1огта! (4) ! яз4:: мппя з = роста! (1); / СЬгопо::/оста! ( ) // еггог: нет/огта! () в области видииости Это правило экономит усилия программиста, так как не требует ввода квалифицированных имен, и в то же время не засоряет область видимости так, как это делает директива из!п8 (88.2.3).
Рассмотренное правило особо полезно в случае операндов перегружаемых операций 511.2.4) и аргументов шаблонов (8С.13.8.4), где явная квалификация может быть особо обременительной. Важно, однако, чтобы при этом само пространство имен находилось в области видимости, а функция была объявлена до ее использования. Естественно, что функция может иметь аргументы из нескольких пространств имен. Например: чой!Х(Сйгопо::Ва!е И, я!4::я!ниц я) ( !1(4 == я) ( // ... ! е!зе яТ(И == иАияия( 4, 1914" ) ( // ...
) ) В таком случае, функция ищется в текущей (по отношению к ее вызову) области видимости и в пространствах имен ее аргументов (включая классы аргументов и их базовые классы). После этого ко всем найденным функциям применяются обычные правила разрешения перегрузки (87.4). Например, для И==я выполняется поиск орега!ос== в области видимости, окружающей 1(), в пространстве имен яв1 (где определяется операция == для стандартного библиотечного типа язг!пя) и в простран- Глава 8.
Пространства имен и исключения 234 стве имен СЬ«опо. При этом находится операция вп(:: орегагог== (), но у нее нет аргумента типа Риге, так что используется СЬ опо:: оре«ага«== (), имеющая такой аргумент. См. также 811.2.4. Когда член класса вызывает именованную функцию, остальные члены этого класса и его базовых классов имеют предпочтение перед функциями, выбираемыми на основании типов аргументов; ситуация же с перегруженными операциями иная (811.2.1, 811.2.4). 8.2.7. Псевдонимы пространств имен Если давать пространствам имен короткие имена, то они могут войти в конфликт друг с другом: //слишком коротко (может войти в конфликт) натеврасе А // ...
А::51«1па в1 = "Спе"; А::51«та л2 = «1«1еглен"; В то же время, длинные имена использовать в реальном коде не очень удобно: /У слитком длинное иатекрасе Атегкан Те)ераоне апй Те(еегарй //... ) Атегкап Те!ерлопе апИ Те1еягарЬ::Бл!пя вЗ = "Спея" ! Атегкан Те!ераоне ап4 Те!еягарй::51«те в4 = ий)е)веп«) Дилемма разрешается с помощью коротких псевдонимов (абавев) для длинных имен: /У используем псевдонимы: патеврасе А ТТ = Атегкан Те!ерьопе апй Те(еягарл ! АТТ::51ппд вЗ = "Спев"; АТТ::Я~пни в4 = "Же!вен" / С помошью псевдонимов удобно ссылаться на большой набор объявлений («библиотекуи), точно указывая библиотеку в единственной строчке кода.
Например: патеврасе 1лЬ = гоиидаг(оп 6Ьгагу «2г11; У... 1лЬ:: лег в; 1лЬ::Ж«1па в5 = "Б(Ье11иви; Это кардинально упрошает проблему смены версии библиотеки. Непосредственно применяя ПЬ вместо гонт!апов !1Ь«агу «2г11, мы можем легко перейти к версии "«3«02" изменением одной лишь инициализации псевдонима 1лЬ и перекомпиляцией. Перекомпиляция может выявить возможные рассогласования на уровне исходного кода. В то же время, избыточное применение псевдонимов затрудняет понимание кода и ведет к путанице.
8.2. Пространства имен 8.2.8. Композиция пространств имен Часто возникает необходимость скомбинировать интерфейс из ряда существующих интерфейсов. Например: патезрасе Ни з<гтд ( с<аяя Я<с<па ( /* ... */ ) < Я<я<па орега<ог+ (сопя< Я<г!лая, сопя< Ям!лая ) < йгте орега<ог+ (сопя< В<я<лая, сопя< сваг*) < яоЫ!<П(сваг) < /...
) патеярасе Нег вес<ос <етр<а<е<с<аяя Т> с<вяз )гес<ог ( /* ... */ ) < /... ) ла<пезрасе Му ПЬ ( ия!пе лате<расе НЬ пппд< иыпх патеярасе Нег вес<о< < юЫ ту !с<(а<я<па); После этого мы можем писать программу в терминах Му ПЬ: юЫ5'() ( Му ПЬ:: В<с<ля я = н Пугал" < р... ) // находит Му ПЬ «Н<з я<Пня:: 5<с<ля ия!ле патезрасе Му ПЬ< яоЫ е ( )ес<ог<Б<г<лд) я яя) П... ту ~с<(яя[5) ); //...
//еггог< никакого!)ПО в Му ПЬ нет ю1ПМу !ЬЬ< ьПП(сваг с] ( // ... ) яоЫ НЫ яп <ля <:5)П(сваг с) // оЫ ЯЩ обълвяена в Ни з«япд Если явно квалифицированное имя (такое как Му ПЬ: < Ю<г<пВ) не объявляется в указанном пространстве имен, то компилятор ищет его в пространствах имен, указанных через директивы пз(пВ (например, в Ни я<г<пВ). Истинное (конечное) пространство имен требуется указывать лишь в определениях: 236 Глава 8. Пространства имен и исключения ( ~У... ) гоЫМу г)Ь::ту усг(Я!Наля г) У о)с; Ягггпд есть Му ))Ь:: Я!Мир«в У смысле НЬ Б(ппя:: Б(мпя В идеале, пространство имен должно: 1.
Отражать логически связанный набор элементов. 2. Ограничивать доступ пользователей к не предназначенным для них элементам. 3. Не требовать излишних усилий при использовании. Техника композиции пространств имен, рассматриваемая в текущем и последующих разделах, совместно с препроцессорными директивами ()!пс!и»2е (89.2.1), обеспечивают необходимую поддержку этих требований. 8.2.8.1. Отбор отдельных элементов из пространства имен Иногда нам нужен доступ лишь к некоторым элементам из пространства имен. Для этого можно объявить пространство имен, содержащее лишь необходимые элементы.
Например, мы могли бы объявить иную версию НЬ летая, содержащую только класс Ягг!пя и перегруженные операции конкатенации: патеярасе НЬ я!егия Юли»иь часть иэ Н(я Лппя ( с!вял Я!ггпу ( /* ... *l ) ! Я!с!па орегагог» (сопя!Я!с!пах, сопя!Я!с(пеа); Яь)пя орегагог» (сопл Яэг)пяа, сопя! сваг* ) ! ) Однако если я не являюсь разработчиком или программистом, сопровождающим код, то такой подход быстро приведет к хаосу. Изменения в «настоящем» НЬ ягг!п8 никак не отражаются в данном объявлении. Отбор отдельных элементов из некоторого пространства имен следует явным образом выполнять с помощью объявлений ия!пд: патеярасе Му ягг)пя ( ия!пд НЬ я!с!па::Ягг)пя! игцпя НЬ ятппя:: орегагог«! Юлюбой о иэ Ни ягггпе Объявление ия!пя вносит имя в текущую область видимости.
В частности, единственное объявление ия!пя вносит в область видимости все имеющиеся варианты перегруженных функций. В таком случае, если разработчик НЬ ягг!пя внесет новую функцию-член в класс Ягг!пя, или добавит новый вариант перегруженной операции конкатенации, то эти изменения стануг автоматически доступными пользователям Му ягг!пя. Если же из НЬя ягг!пя улаляется некоторый элемент или какой-то его элемент изменяется, то ставшее при этом некорректным применение Му ягг!пя сразу же будет обнаружено компилятором (см. также 815.2.2). 2ЗТ 8 2.