Пространство имен позволяет сгруппировать функционал в отдельные контейнеры. Пространство имен представляет блок кода, который содержит набор компонентов (функций, классов и т.д.) и имеет некоторое имя,
которое прикрепляется к каждому компоненту из этого пространства имен. Полное имя каждого компонента — это имя пространства имен, за которым следует оператор
:: (оператор области видимости или scope operator) и имя компонента. Примером может служить оператор cout
,
который предназначен для вывода строки на консоль и который определен в пространстве имен std. Соответственно чтобы обратиться к этому оператору, применяется
выражение std::cout
.
Если пространство имен не указано, то по умолчанию применяется глобальное пространство имен. применяется по умолчанию, если пространство имен не было определено. Все имена в глобальном пространстве имен такие же, как вы их объявляете, без прикрепления имени пространства имен. Например:
#include <iostream> void print(const std::string&); const std::string message{"hello"}; int main() { print(message); } void print(const std::string& text) { std::cout << text << std::endl; }
Здесь определены функции print и main и константа message и не используется никакого пространства имен. Поэтому фактически функции print и main и константа message определены в глобальном пространстве имен. В принципе для обращения к ним также можно использовать оператор ::, только без названия пространства имен, хотя это и избыточно:
int main() { ::print(::message); }
Стоит отметить, что функция main
должна быть определена в глобальном пространстве имен.
Теперь рассмотрим, как определять и использовать свои пространства имен.
Для определения пространства имен применяется ключевое слово namespace, за которым идет название имени пространства имен:
namespace имя_пространства_имен { // код пространства имен }
После имени пространства имен идет блок кода, в который собственно помещаются компоненты пространства имен - функции, классы и т.д.
Например, определим пространство имен, которое назовем hello:
#include <iostream> namespace hello { const std::string message{"hello work"}; void print(const std::string& text) { std::cout << text << std::endl; } } int main() { hello::print(hello::message); // hello work }
Здесь в пространстве hello определена функция print и константа message. И чтобы обратиться к этим компонентам вне пространства имен hello, надо использовать его имя:
hello::print(hello::message);
Внутри пространства имен к его компонентам можно обращаться без имени пространства имен:
namespace hello { const std::string message{"hello work"}; void print(const std::string& text) { std::cout << text << std::endl; } void print_default() { std::cout << message << std::endl; } }
Одно пространство имен может содержать другие пространства:
#include <iostream> namespace console { namespace messages { const std::string hello{"hello"}; const std::string welcome{"Welcome"}; const std::string goodbye{"Good bye"}; } void print(const std::string& text) { std::cout << text << std::endl; } void print_default() { std::cout << messages::hello << std::endl; } } int main() { console::print(console::messages::hello); }
Здесь в пространстве console определено вложенное пространство messages, которое содержит ряд констант. Для обращения к компонентам вложенного пространства имен также надо использовать его имя:
void print_default() { std::cout << messages::hello << std::endl; }
Вне пространства имен console для обращения к подобным констанстам надо указывать всю цепь пространств имен:
int main() { console::print(console::messages::hello); // console { messages { hello}} }
Директива using позволяет ссылаться на любой компонент пространства имен без использования его имени:
#include <iostream> namespace console { const std::string message{"hello"}; void print(const std::string& text) { std::cout << text << std::endl; } } using namespace console; // подключаем все компоненты пространства console int main() { print(message); // указывать пространство имен не требуется }
Здесь подключаем все компоненты пространства имен console в глобальное пространство имен. И после этого указывать имя этого пространства для обращения к его компонентам не требуется:
using namespace console; // подключаем все компоненты пространства console int main() { print(message); // указывать пространство имен не требуется }
Однако такое подключение может привести к нежелательным последствиям, если в глобальном пространстве имен определяются компоненты с теми же именами (например, переменная message). В этом случае мы можем подключить только отдельные компоненты:
#include <iostream> namespace console { const std::string message{"hello"}; void print(const std::string& text) { std::cout << text << std::endl; } } using console::print; // подключаем только функцию print int main() { print(console::message); // надо указывать пространство для message }
Здесь подключаем только функцию print:
using console::print;
Поэтому для обращения к ней не надо указывать имя пространства имен. А для обращения к любым другим компонентам надо.
Если название пространства длинное, то для него можно определить псевдоним:
namespace псевдоним = название пространства имен;
Например:
#include <iostream> namespace console { namespace messages { const std::string message{"hello"}; } void print(const std::string& text) { std::cout << text << std::endl; } } namespace mes = console::messages; int main() { console::print(mes::message); // обращаемся к message через псевдоним mes }
В данном случае для пространства console::messages
устанавливается псевдоним mes
.