Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Использование членов пространства имен А
Использование квалифицированных имен при каждом обращении к членам пространств может стать обременительным, особенно если имена пространств достаточно длинны. Если бы удалось сделать их короче, то такие имена проще было бы читать и набивать. Однако употребление коротких имен увеличивает риск их совпадения с другими, поэтому желательно, чтобы в библиотеках применялись пространства с длинными именами. К счастью, существуют механизмы, облегчающие использование членов пространств имен в программах. Псевдонимы пространства имен, using-объявления и using-директивы помогают преодолеть неудобства работы с очень длинными именами. Псевдонимы пространства имен Псевдоним пространства имен используется для задания короткого синонима имени пространства. Например, длинное имя
{ /*... */ } может быть ассоциировано с более коротким синонимом: namespace IBM = International_Business_Machines; Объявление псевдонима начинается ключевым словом namespace, за которым следует короткий псевдоним, а за ним – знак равенства и исходное полное имя пространства. Если полное имя не соответствует никакому известному пространству, это ошибка. Псевдоним может относиться и к вложенному пространству имен. Вспомним слишком длинное определение функции func() выше:
} Разрешается задать псевдоним для обозначения вложенного cplusplLis_primer:: MatrixLib, сделав определение функции более удобным для восприятия:
} Одно пространство имен может иметь несколько взаимозаменяемых псевдонимов. Например, если псевдоним Lib ссылается на cplusplus_primer, то определение функции func () может выглядеть и так:
} Using-объявления Имеется механизм, позволяющий обращаться к членам пространства имен, используя их имена без квалификатора, т.е. без префикса namespace_name::. Для этого применяются using-объявления. Using-объявление начинается ключевым словом using, за которым следует квалифицированное имя члена пространства. Например:
using cplusplus_primer:: MatrixLib:: matrix; Using-объявление вводит имя в ту область видимости, в которой оно использовано. Так, предыдущее using-объявление делает имя matrix глобально видимым. После того как это объявление встретилось в программе, использование имени matrix в глобальной области видимости или во вложенных в нее областях относится к этому члену пространства имен. Пусть далее идет следующее объявление: void func( matrix & m ); Оно вводит функцию func() с параметром типа cplusplus_primer:: MatrixLib:: matrix. Using-объявление ведет себя подобно любому другому объявлению: оно имеет область видимости, и имя, введенное им, можно употреблять начиная с места объявления и до конца области видимости. Using-объявление может использоваться в глобальной области видимости, равно как и в области видимости любого пространства имен. Оно употребляется и в локальной области. Имя, вводимое using-объявлением, как и любым другим, имеет следующие характеристики: · оно должно быть уникальным в своей области видимости; · оно скрывает одноименную сущность во внешней области; · оно скрывается объявлением одноименной сущности во вложенной области. Например:
// надо использовать blip:: bk Using-объявления в функции manip() позволяют ссылаться на членов пространства blib с помощью неквалифицированных имен. Такие объявления не видны вне manip(), и неквалифицированные имена могут применяться только внутри этой функции. Вне ее необходимо употреблять квалифицированные имена. Using-объявление упрощает использование членов пространства имен. Оно вводит только одно имя. Using-объявление может находиться в определенной области видимости, и, значит, мы способны точно указать, в каком месте программы те или иные члены разрешается употреблять без дополнительной квалификации. В следующем подразделе мы расскажем, как ввести в определенную область видимости все члены некоторого пространства имен. Using-директивы Пространства имен появились в стандартном С++. Предыдущие версии С++ их не поддерживали, и, следовательно, поставляемые библиотеки не помещали глобальные объявления в пространства имен. Множество программ на С++ было написано еще до того, как компиляторы стали поддерживать такую опцию. Заключая содержимое библиотеки в пространство имен, мы можем испортить старое приложение, использующее ее предыдущие версии: все имена из этой библиотеки становятся квалифицированными, т.е. должны включать имя пространства вместе с оператором разрешения области видимости. Те приложения, в которых эти имена употребляются в неквалифицированной форме, перестают компилироваться. Сделать видимыми имена из библиотеки, используемой в нашей программе, можно с помощью using-объявления. Предположим, что файл primer.h содержит интерфейс новой версии библиотеки, в котором глобальные объявления помещены в пространство имен cplusplus_primer. Нужно заставить нашу программу работать с новой библиотекой. Два using-объявления сделают видимыми имена класса matrix и функции inverse() из пространства cplusplus_primer:
} Но если библиотека достаточно велика и приложение часто использует имена из нее, то для подгонки имеющегося кода к новой библиотеке может потребоваться много using-объявлений. Добавлять их все только для того, чтобы старый код скомпилировался и заработал, утомительно и чревато ошибками. Решить эту проблему помогают using-директивы, облегчающие переход на новую версию библиотеки, где впервые стали применяться пространства имен. Using-директива начинается ключевым словом using, за которым следует ключевое слово namespace, а затем имя некоторого пространства имен. Это имя должно ссылаться на определенное ранее пространство, иначе компилятор выдаст ошибку. Using-директива позволяет сделать все имена из этого пространства видимыми в неквалифицированной форме. Например, предыдущий фрагмент кода может быть переписан так:
} Using-директива делает имена членов пространства имен видимыми за его пределами, в том месте, где она использована. Например, приведенная using-директива создает иллюзию того, что все члены cplusplus_primer объявлены в глобальной области видимости перед определением func(). При этом члены пространства имен не получают локальных псевдонимов, а как бы перемещаются в новую область видимости. Код
} выглядит как int i, j; для фрагмента программы, содержащего в области видимости следующую using-директиву: using namespace A; Рассмотрим пример, позволяющий подчеркнуть разницу между using-объявлением (которое сохраняет пространство имен, но создает ассоциированные с его членами локальные синонимы) и using-директивой (которая полностью удаляет границы пространства имен).
} Во-первых, using-директивы имеют область видимости. Такая директива в функции manip() относится только к блоку этой функции. Для manip() члены пространства имен blip выглядят так, как будто они объявлены в глобальной области видимости, а следовательно, можно использовать их неквалифицированные имена. Вне этой функции необходимо употреблять квалифицированные. Во-вторых, ошибки неоднозначности, вызванные применением using-директивы, обнаруживают себя при реальном обращении к такому имени, а не при встрече в тексте самой этой директивы. Например, переменная bj, член пространства blib, выглядит для manip() как объявленная в глобальной области видимости, вне blip. Однако в глобальной области уже есть такая переменная. Возникает неоднозначность имени bj в функции manip(): оно относится и к глобальной переменной, и к члену пространства blip. Ошибка проявляется только при упоминании bj в функции manip(). Если бы это имя вообще не использовалось в manip(), коллизия не проявилась бы. В-третьих, using-директива не затрагивает употребление квалифицированных имен. Когда в manip() упоминается:: bj, имеется в виду переменная из глобальной области видимости, а blip:: bj обозначает переменную из пространства имен blip. И наконец члены пространства blip выглядят для функции manip() так, как будто они объявлены в глобальной области видимости. Это означает, что локальные объявления внутри manip() могут скрывать имена членов пространства blip. Локальная переменная bk скрывает blip:: bk. Ссылка на bk внутри manip() не является неоднозначной – речь идет о локальной переменной. Using-директивы использовать очень просто: стоит написать одну такую директиву, и все члены пространства имен сразу становятся видимыми. Однако чрезмерное увлечение ими возвращает нас к старой проблеме засорения глобального пространства имен:
// cplusplus_primer:: matrix или DisneyFeatureAnimation:: matrix? Ошибки неоднозначности, вызываемые using-директивой, обнаруживаются только в момент использования. В данном случае – при употреблении имени matrix. Такая ошибка, найденная не сразу, может стать сюрпризом: заголовочные файлы не менялись и никаких новых объявлений в программу добавлено не было. Ошибка появилась после того, как мы решили воспользоваться новыми средствами из библиотеки. Using-директивы очень полезны при переводе приложений на новые версии библиотек, использующие пространства имен. Однако употребление большого числа using-директив возвращает нас к проблеме засорения глобального пространства имен. Эту проблему можно свести к минимуму, если заменить using-директивы более селективными using-объявлениями. Ошибки неоднозначности, вызываемые ими, обнаруживаются в момент объявления. Мы рекомендуем пользоваться using-объявлениями, а не using-директивами, чтобы избежать засорения глобального пространства имен в своей программе. |
Последнее изменение этой страницы: 2019-04-09; Просмотров: 282; Нарушение авторского права страницы