С.Б. Липпман, Ж. Лажойе - Язык программирования С++ Вводный курс (1114944), страница 69
Текст из файла (страница 69)
Определение такогопространства начинается ключевым словом namespace. Очевидно, что никакого имени заэтим словом нет, а сразу же идет блок в фигурных скобках, содержащий различные// ----- SortLib.C ----namespace {void swap( double *dl, double *d2 ) { /* ... */ }}объявления. Например:// определения функций сортировки не изменяютсяФункция swap() видна только в файле SortLib.C. Если в другом файле в безымянномпространстве имен содержится определение swap(), то это другая функция. Наличиедвух функций swap() не является ошибкой, поскольку они различны. Безымянныепространства имен отличаются от прочих: определение такого пространства локально дляодного файла и не может размещаться в нескольких.Имя swap() может употребляться в неквалифицированной форме в файле SortLib.Cпосле определения безымянного пространства.
Оператор разрешения области видимостиvoid quickSort( double *d1, double *d2 ) {// ...double* elem = d1;// ...// ссылка на член безымянного пространства имен swap()swap( d1, elem );// ...для ссылки на его члены не нужен.}Члены безымянного пространства имен относятся к сущностям программы. Поэтомуфункция swap() может быть вызвана во время выполнения. Однако имена этих членоввидны только внутри одного файла.До того как в стандарте С++ появилось понятие пространства имен, наиболее удачнымрешением проблемы локализации было использование ключевого слова static,унаследованного из С.
Член безымянного пространства имеет свойства, аналогичныеглобальной сущности, объявленной как static. В языке С такая сущность невидима внефайла, в котором объявлена. Например, текст из SortLib.C можно переписать на С,// SortLib.C// swap() невидима для других файлов программыstatic void swap( double *d1, double *d2 ) { /* ... */ }сохранив свойства swap():412С++ для начинающих// определения функций сортировки такие же, как и раньшеВо многих программах на С++ используются объявления с ключевым словом static.Предполагается, что они должны быть заменены безымянными пространствами имен помере того, как все большее число компиляторов начнет поддерживать это понятие.Упражнение 8.11Зачем нужно определять собственное пространство имен в программе?Упражнение 8.12Имеется следующее объявление operator*(), члена вложенного пространства именnamespace cplusplus_primer {namespace MatrixLib {class matrix { /*...*/ };matrix operator* ( const matrix &, const matrix & );// ...}cplusplus_primer::MatrixLib:}Как определить эту функцию в глобальной области видимости? Напишите толькопрототип.Упражнение 8.13Объясните, зачем нужны безымянные пространства имен.8.6.
Использование членов пространства имен АИспользование квалифицированных имен при каждом обращении к членам пространствможет стать обременительным, особенно если имена пространств достаточно длинны.Если бы удалось сделать их короче, то такие имена проще было бы читать и набивать.Однако употребление коротких имен увеличивает риск их совпадения с другими, поэтомужелательно, чтобы в библиотеках применялись пространства с длинными именами.К счастью, существуют механизмы, облегчающие использование членов пространствимен в программах. Псевдонимы пространства имен, using-объявления и usingдирективы помогают преодолеть неудобства работы с очень длинными именами.8.6.1. Псевдонимы пространства именПсевдоним пространства имен используется для задания короткого синонима имениnamespace International_Business_Machinesпространства. Например, длинное имя{ /* ...
*/ }может быть ассоциировано с более коротким синонимом:413С++ для начинающихnamespace IBM = International_Business_Machines;Объявление псевдонима начинается ключевым словом namespace, за которым следуеткороткий псевдоним, а за ним – знак равенства и исходное полное имя пространства.Если полное имя не соответствует никакому известному пространству, это ошибка.Псевдоним может относиться и к вложенному пространству имен. Вспомним слишком#include "primer.h"// трудно читать!void func( cplusplus_primer::MatrixLib::matrix &m ){// ...cplusplLis_primer::MatrixLib::inverse( m );return m;длинное определение функции func() выше:}РазрешаетсязадатьпсевдонимдляобозначениявложенногоcplusplLis_primer::MatrixLib, сделав определение функции более удобным для#include "primer.h"// более короткий псевдонимnamespace mlib = cplusplus_primer::MatrixLib;// читать проще!void func( mlib::matrix &m ){// ...mlib::inverse( m );return m;восприятия:}Одно пространство имен может иметь несколько взаимозаменяемых псевдонимов.Например, если псевдоним Lib ссылается на cplusplus_primer, то определение// псевдоним alias относится к пространству имен cplusplus_primernamespace alias = Lib;void func( cplusplus_primer::matrix &m ) {// ...alias::inverse( m );return m;функции func() может выглядеть и так:}414С++ для начинающих4158.6.2.
Using-объявленияИмеется механизм, позволяющий обращаться к членам пространства имен, используя ихимена без квалификатора, т.е. без префикса namespace_name::. Для этого применяютсяusing-объявления.Using-объявлениеначинаетсяключевымсловомusing,закоторымследуетnamespace cplusplus_primer {namespace MatrixLib {class matrix { /* ... */ };// ...}}// using-объявление для члена matrixквалифицированное имя члена пространства. Например:using cplusplus_primer::MatrixLib::matrix;Using-объявление вводит имя в ту область видимости, в которой оно использовано.
Так,предыдущее using-объявление делает имя matrix глобально видимым.После того как это объявление встретилось в программе, использование имени matrix вглобальной области видимости или во вложенных в нее областях относится к этомучлену пространства имен. Пусть далее идет следующее объявление:void func( matrix &m );Оно вводит функциюMatrixLib::matrix.func()спараметромтипаcplusplus_primer::Using-объявление ведет себя подобно любому другому объявлению: оно имеет областьвидимости, и имя, введенное им, можно употреблять начиная с места объявления и доконца области видимости.
Using-объявление может использоваться в глобальной областивидимости, равно как и в области видимости любого пространства имен. Оноупотребляется и в локальной области. Имя, вводимое using-объявлением, как и любымдругим, имеет следующие характеристики:•оно должно быть уникальным в своей области видимости;•оно скрывает одноименную сущность во внешней области;•оно скрывается объявлением одноименной сущности во вложенной области.Например:С++ для начинающих416namespace blip {int bi = 16, bj = 15, bk = 23;// прочие объявления}int bj = 0;void manip() {using blip::bi; // bi в функции manip() ссылается на blip::bi++bi;// blip::bi == 17using blip::bj; // скрывает глобальную bj// bj в функции manip()ссылается на blip::bj++bj;// blip::bj == 16int bk;// объявление локальной bkusing blip::bk; // ошибка: повторное определение bk в manip()}int wrongInit = bk; // ошибка: bk невидима// надо использовать blip::bkUsing-объявления в функции manip() позволяют ссылаться на членов пространства blibс помощью неквалифицированных имен.
Такие объявления не видны вне manip(), инеквалифицированные имена могут применяться только внутри этой функции. Вне еенеобходимо употреблять квалифицированные имена.Using-объявление упрощает использование членов пространства имен. Оно вводит толькоодно имя. Using-объявление может находиться в определенной области видимости, и,значит, мы способны точно указать, в каком месте программы те или иные членыразрешается употреблять без дополнительной квалификации.В следующем подразделе мы расскажем, как ввести в определенную область видимостивсе члены некоторого пространства имен.8.6.3. Using-директивыПространства имен появились в стандартном С++. Предыдущие версии С++ их неподдерживали, и, следовательно, поставляемые библиотеки не помещали глобальныеобъявления в пространства имен. Множество программ на С++ было написано еще дотого, как компиляторы стали поддерживать такую опцию.
Заключая содержимоебиблиотеки в пространство имен, мы можем испортить старое приложение,использующее ее предыдущие версии: все имена из этой библиотеки становятсяквалифицированными, т.е. должны включать имя пространства вместе с операторомразрешения области видимости. Те приложения, в которых эти имена употребляются внеквалифицированной форме, перестают компилироваться.Сделать видимыми имена из библиотеки, используемой в нашей программе, можно спомощью using-объявления. Предположим, что файл primer.h содержит интерфейсновой версии библиотеки, в котором глобальные объявления помещены в пространствоимен cplusplus_primer. Нужно заставить нашу программу работать с новойбиблиотекой. Два using-объявления сделают видимыми имена класса matrix и функцииinverse() из пространства cplusplus_primer:С++ для начинающих#include "primer.h"using cplusplus_primer::matrix;using cplusplus_primer::inverse;// using-объявления позволяют использовать// имена matrix и inverse без спецификацииvoid func( matrix &m ) {// ...inverse( m );return m;}Но если библиотека достаточно велика и приложение часто использует имена из нее, тодля подгонки имеющегося кода к новой библиотеке может потребоваться много usingобъявлений.
Добавлять их все только для того, чтобы старый код скомпилировался изаработал, утомительно и чревато ошибками. Решить эту проблему помогают usingдирективы, облегчающие переход на новую версию библиотеки, где впервые сталиприменяться пространства имен.Using-директива начинается ключевым словом using, за которым следует ключевое словоnamespace, а затем имя некоторого пространства имен. Это имя должно ссылаться наопределенное ранее пространство, иначе компилятор выдаст ошибку. Using-директивапозволяет сделать все имена из этого пространства видимыми в неквалифицированнойформе.#include "pnmer.h"// using-директива: все члены cplusplus_primer// становятся видимымиusing namespace cplusplus_primer;// имена matrix и inverse можно использовать без спецификацииvoid func( matrix &m ) {// ...inverse( m );return m;Например, предыдущий фрагмент кода может быть переписан так:}Using-директива делает имена членов пространства имен видимыми за его пределами, втом месте, где она использована.