|
Программирование >> Инициализация объектов класса, структура
#include primer.h using cplusplus primer::matrix; using cplusplus primer::inverse; using-объявления позволяют использовать имена matrix и inverse без спецификации void func( matrix &m ) { ... verse 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 & void func( matrix &m ) / / inverse( m ); return m; Например, предыдущий фрагмент кода может быть переписан так: Using-директива делает имена членов пространства имен видим1ми за его пределами, в том месте, где она использована. Например, приведенная using-директива создает иллюзию того, что все члены cplusplus primer объявлены в глобальной области видимости перед определением func() . При этом члены пространства имен не получают namespace A { int i, j; локальных псевдонимов, а как бы перемещаются в новую область видимости. Код выглядит как namespace blip { int bi = 16, bj = 15, bk = 23; прочие объявления int bj = 0; void manip() { using namespace blip; using-директива - коллизия имен ::bj and blip::bj обнаруживается только при использовании bj ++bi; blip::bi == 17 ++bj; ошибка: неоднозначность глобальная bj blip::bj? ++::bj; правильно: глобальная bj == 1 ++blip::bj; правильно: blip::bj == 16 int bk = 97; локальная bk скрает blip::bk ++bk; локальная bk == 98 пространства имен). Во-нервых, using-директивы имеют область видимости. Такая директива в функции manip() относится только к блоку этой функции. Для manip() члены пространства имен blip выглядят так, как будто они объявлены в глобальной области видимости, а следовательно, можно использовать их неквалифицированные имена. Вне этой функции необходимо употреблять квалифицированные. Во-вторгх, ошибки неоднозначности, вызванные применением using-директивы, обнаруживают себя при реальном обращении к такому имени, а не при встрече в тексте самой этой директивы. Например, переменная bj, член пространства blib, выглядит для manip() как объявленная в глобальной области видимости, вне blip. Однако в глобальной области уже есть такая переменная. Возникает неоднозначность имени bj в функции manip(): оно относится и к глобальной переменной, и к члену пространства blip. Ошибка проявляется только при упоминании bj в функции manip() . Если бы это имя вообще не использовалось в manip() , коллизия не проявилась бы. В-третьих, using-директива не затрагивает употребление квалифицированнгх имен. Когда в mianipO упоминается ::bj, имеется в виду неременная из глобальной области видимости, а blip::bj обозначает переменную из пространства имен blip. И наконец члены пространства blip выглядят для функции manip() так, как будто они объявлен! в глобальной области видимости. Это означает, что локальные объявления внутри mianipO могут скрывать имена членов пространства blip. Локальная int i, j; для фрагмента программы, содержащего в области видимости следующую using-директиву: using namespace A; Рассмотрим пример, позволяющий подчеркнуть разницу между using-объявлением (которое сохраняет пространство имен, но создает ассоциированные с его членами локальные синоним:) и using-директивой (которая полностью удаляет границы namespace cplusplus primer { class matrix { }; прочие вещи ... namespace DisneyFeatureAnimation { class matrix { }; здесь тоже ... using namespace cplusplus primer; using namespace DisneyFeatureAnimation; matrix m; ошибка, неоднозначность: возвращает нас к старой проблеме засорения глобального пространства имен: cplusplus primer::matrix DisneyFeatureAnimation::matrix? Ошибки неоднозначности, вызываемые using-директивой, обнаруживаются только в момент использования. В данном случае - при употреблении имени matrix. Такая ошибка, найденная не сразу, может стать сюрпризом: заголовочные файлы не менялись и никаких новых объявлений в программу добавлено не было. Ошибка появилась после того, как мы решили воспользоваться новыми средствами из библиотеки. Using-директивы очень полезны при переводе приложений на новые версии библиотек, использующие пространства имен. Однако употребление большого числа using-директив возвращает нас к проблеме засорения глобального пространства имен. Эту проблему можно свести к минимуму, если заменить using-директивы более селективными using-объявлениями. Ошибки неоднозначности, вызываемые ими, обнаруживаются в момент объявления. Мы рекомендуем пользоваться using-объявлениями, а не using-директивами, чтобы избежать засорения глобального пространства имен в своей программе. 8.6.4. Стандартное пространство имен std Все компоненты стандартной библиотеки С++ находятся в пространстве имен std. Каждая функция, объект и шаблон класса, объявленные в стандартном заголовочном файле, таком, как <vector> или <iostreami>, принадлежат к этому пространству. Если все компоненты библиотеки объявлены в std, то какая ошибка допущена в данном примере: переменная bk скрывает blip::bk. Ссылка на bk внутри manip() не является неоднозначной - речь идет о локальной переменной. Using-директивы использовать очень просто: стоит написать одну такую директиву, и все члены пространства имен сразу становятся видимыми. Однако чрезмерное увлечение ими
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |