Импорт всего пространства имен часто является плохой идеей и обычно рассматривается как плохой стиль. В примерах в этой книге мы импортируем полное содержимое пространства имен std
При импорте всего пространства имен или даже нескольких пространств имен их полезность значительно снижается. Одной из причин существования пространств имен является снижение конфликтов имен. При импорте нескольких различных пространств имен вероятность конфликтов имен увеличивается. В данный момент код может прекрасно компилироваться, но в будущем в одно из пространств имен может быть что-то добавлено, и при последующей сборке кода возникнет конфликт.
Чтобы разделить содержимое пространства имен на более мелкие группы, можно использовать вложенные пространства имен. Например, пространство имен hardware
namespace hardware {
namespace net {
// сетевые классы
}
namespace devices {
// классы устройств
}
}
Теперь доступ к элементам, содержащимся в пространстве имен, стал несколько более сложным.
// В каком-либо другом файле...
using hardware::devices::Device;
Пространства имен довольно удобны. Есть несколько интересных вещей, связанных с пространствами имен, облегчающих жизнь: псевдонимы пространств имен, автоматический поиск имен в пространствах имен параметров функций и подстановка имен перегрузок функций в объявлениях using
Псевдоним пространства имен — это то, что означает его название: имя (возможно, короткое), которое используется для замены имени (возможно, длинного) пространства имен. Если вы не хотите использовать выражение using
using dev = hardware::devices;
// ...
dev::Device d;
Затем этот псевдоним используется при ссылке на элементы соответствующего пространства имен.
C++ также предоставляет автоматический поиск в пространствах имен, к которым относятся параметры функций. Так, например, следующий код описывает аргументы в пространстве имен (dev
Device
):void f(dev::Device& d) {
register(d); // на самом деле это dev::register
}
При передаче функции параметра, принадлежащего пространству имен, компилятор включает это пространство имен при поиске имен функций, вызываемых в теле этой функции. Это, может быть, не самая часто используемая особенность, но когда она используется, то экономит значительное время набора кода и позволяет избежать лишних директив using
Последним интересным моментом, связанным с пространствами имен, является подстановка имен перегрузок в объявлениях using
namespace mylib {
void foo(mt);
void foo(double);
void foo(std::string);
// Другие перегрузки foo( )...
}
// В каком-то другом файле...
using mylib::foo; // Какой вариант используется?
Объявление using
foo
, так что писать отдельную директиву для каждой перегрузки не требуется. Другим преимуществом этой записи является то, что если добавляется еще одна перегрузка foo
, то весь код, содержащий объявление вида mylib::foo
, видит ее автоматически (конечно, при компиляции кода, содержащего это объявление), так как объявление using
включает и ее.Конечно, использовать пространства имен следует обдуманно, а иначе у вас или тех, кто будет их использовать, появятся неожиданные ошибки компиляции. Вот несколько популярных советов по использованию пространств имен.
using namespace xxx
Как я объяснял ранее, импорт всего пространства имен увеличивает вероятность конфликта имен — либо сразу, либо в будущем (в используемое вами пространство имен может быть добавлено что-то, что приведет к конфликту). Это также снижает степень модульности, предоставляемую пространствами имен.
using