using
Директивы using
, вводящие в область видимости все имена из пространства имен, обманчиво просты в использовании. Единственный оператор делает видимыми имена всех членов пространства имен. Хоть этот подход может показаться простым, он создает немало проблем. Если в приложении использовано много библиотек и директива using
сделает видимыми имена, определенные в них, то вновь возникнет проблема загромождения глобального пространства имен.
Кроме того, не исключено, что при выходе новой версии библиотеки вполне работоспособная в прошлом программа перестанет компилироваться. Причиной этой проблемы может быть конфликт имен новой версии с именами, которые использовались прежде.
Еще одна вызванная директивой using
проблема неоднозначности обнаруживается только в момент применения. Столь позднее обнаружение означает, что конфликты могут возникать значительно позже применения определенной библиотеки. То есть при использовании в программе новой библиотеки могут возникнуть не обнаруженные ранее конфликты.
Поэтому лучше не полагаться на директиву using
и использовать объявление using
для каждого конкретного имени пространства имен, используемого в программе. Это уменьшит количество имен, вводимых в пространство имен. Кроме того, ошибки неоднозначности, причиной которых является объявление using
, обнаруживаются в точке объявления, а это существенно упрощает их поиск.
using
на самом деле полезны в файлах реализации самого пространства имен.
Упражнение 18.15. Объясните различия между объявлением и директивой using
.
Упражнение 18.16. Объясните следующий код с учетом того, что объявления using
для всех членов пространства имен Exercise
находятся в области, помеченной как
. Что, если вместо этого они располагаются в
? Теперь ответьте на тот же вопрос, но замените объявления using
директивой using
для пространства имен Exercise
.
namespace Exercise {
int ivar = 0;
double dvar = 0;
const int limit = 1000;
}
int ivar = 0;
//
void manip() {
//
double dvar = 3.1416;
int iobj = limit + 1;
++ivar;
++::ivar;
}
Упражнение 18.17. Напишите код для проверки ответов на предыдущий вопрос.
18.2.3. Классы, пространства имен и области видимости
Поиск имен, используемых в пространстве имен, происходит согласно обычным правилам поиска в языке С++: сначала во внутренней, а затем во внешней области видимости. Имя, используемое в пространстве имен, может быть определено в одном из окружающих пространств имен, включая глобальное пространство имен. Однако учитываются только те имена, которые были объявлены перед точкой использования в блоках, которые все еще открыты.
namespace A {
int i;
namespace В {
int i; //
int j;
int f1() {
int j; //
return i; // возвращает B::i
}
} //
int f2() {
return j; //
}
int j = i; //
}