Внимание! Избегайте директив using

Директивы using, вводящие в область видимости все имена из пространства имен, обманчиво просты в использовании. Единственный оператор делает видимыми имена всех членов пространства имен. Хоть этот подход может показаться простым, он создает немало проблем. Если в приложении использовано много библиотек и директива using сделает видимыми имена, определенные в них, то вновь возникнет проблема загромождения глобального пространства имен.

Кроме того, не исключено, что при выходе новой версии библиотеки вполне работоспособная в прошлом программа перестанет компилироваться. Причиной этой проблемы может быть конфликт имен новой версии с именами, которые использовались прежде.

Еще одна вызванная директивой using проблема неоднозначности обнаруживается только в момент применения. Столь позднее обнаружение означает, что конфликты могут возникать значительно позже применения определенной библиотеки. То есть при использовании в программе новой библиотеки могут возникнуть не обнаруженные ранее конфликты.

Поэтому лучше не полагаться на директиву using и использовать объявление using для каждого конкретного имени пространства имен, используемого в программе. Это уменьшит количество имен, вводимых в пространство имен. Кроме того, ошибки неоднозначности, причиной которых является объявление using, обнаруживаются в точке объявления, а это существенно упрощает их поиск.

Директивы using на самом деле полезны в файлах реализации самого пространства имен.

Упражнения раздела 18.2.2

Упражнение 18.15. Объясните различия между объявлением и директивой using.

Упражнение 18.16. Объясните следующий код с учетом того, что объявления using для всех членов пространства имен Exercise находятся в области, помеченной как позиция 1. Что, если вместо этого они располагаются в позиции 2? Теперь ответьте на тот же вопрос, но замените объявления using директивой using для пространства имен Exercise.

namespace Exercise {

 int ivar = 0;

 double dvar = 0;

 const int limit = 1000;

}

int ivar = 0;

// позиция 1

void manip() {

 // позиция 2

 double dvar = 3.1416;

 int iobj = limit + 1;

 ++ivar;

 ++::ivar;

}

Упражнение 18.17. Напишите код для проверки ответов на предыдущий вопрос.

<p>18.2.3. Классы, пространства имен и области видимости</p>

Поиск имен, используемых в пространстве имен, происходит согласно обычным правилам поиска в языке С++: сначала во внутренней, а затем во внешней области видимости. Имя, используемое в пространстве имен, может быть определено в одном из окружающих пространств имен, включая глобальное пространство имен. Однако учитываются только те имена, которые были объявлены перед точкой использования в блоках, которые все еще открыты.

namespace A {

 int i;

 namespace В {

  int i; // скрывает A::i в В

  int j;

  int f1() {

   int j;    // j локальна для f1() и скрывает A::B::j

   return i; // возвращает B::i

  }

 } // пространство имен В закрыто, и его имена больше не видимы

 int f2() {

  return j; // ошибка: j не определена

 }

 int j = i; // инициализируется значением A::i

}

Перейти на страницу:

Похожие книги