Spații de nume
Spațiul de nume permite gruparea funcționalității în containere separate. Un spațiu de nume reprezintă un bloc de cod care conține un set de componente (funcții, clase etc.) și are un anumit nume care este atașat fiecărei componente din acest spațiu. Numele complet al fiecărei componente este format din numele spațiului de nume urmat de operatorul :: (operatorul de domeniu de vizibilitate). Un exemplu este operatorul cout, care este folosit pentru a afișa un șir de caractere în consolă și care este definit în spațiul de nume std. Astfel, pentru a apela acest operator, se folosește expresia std::cout.
Spațiul de nume global
Dacă spațiul de nume nu este specificat, atunci este folosit implicit spațiul de nume global. Toate numele din spațiul global de nume sunt aceleași cu cele declarate, fără atașarea vreunui nume de spațiu. De exemplu:
#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;
}
Aici funcțiile print și main și constanta message sunt definite în spațiul de nume global. De fapt, putem accesa aceste componente și folosind operatorul :: fără numele spațiului:
int main()
{
::print(::message);
}
De reținut că funcția main trebuie să fie definită în spațiul de nume global.
Definirea unui spațiu de nume
Pentru a defini un spațiu de nume se folosește cuvântul cheie namespace urmat de numele spațiului:
namespace nume_spatiu
{
// codul spațiului de nume
}
După numele spațiului urmează un bloc de cod în care sunt plasate funcțiile, clasele etc.
Exemplu:
#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
}
Aici, în spațiul de nume hello, este definită funcția print și constanta message. Și pentru a accesa aceste componente din afara spațiului de nume hello, trebuie să folosim numele acestuia:
hello::print(hello::message);
În interiorul spațiului de nume, componentele pot fi accesate fără a menționa numele spațiului:
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;
}
}
Spații de nume imbricate
Un spațiu de nume poate conține alte spații de nume:
#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);
}
Aici, în spațiul de nume console, este definit un spațiu intern messages, care conține un set de constante. Pentru a accesa componentele spațiului de nume intern, trebuie să folosim și numele acestuia:
void print_default()
{
std::cout << messages::hello << std::endl;
}
În afara spațiului de nume console, pentru a accesa astfel de constante, trebuie menționată întreaga ierarhie:
int main()
{
console::print(console::messages::hello);
}
Instrucțiunea using
Instrucțiunea using permite accesul la orice componentă a unui spațiu de nume fără a preciza numele spațiului:
#include <iostream>
namespace console
{
const std::string message{"hello"};
void print(const std::string& text)
{
std::cout << text << std::endl;
}
}
using namespace console; // includem toate componentele spațiului `console`
int main()
{
print(message); // nu este nevoie să specificăm spațiul de nume
}
Aici includem toate componentele spațiului de nume console în spațiul global. După aceea, nu mai este necesar să precizăm console:::
using namespace console;
int main()
{
print(message);
}
Totuși, această includere poate duce la conflicte de nume dacă în spațiul global există deja componente cu același nume (de exemplu, message). În acest caz, putem include doar anumite componente:
#include <iostream>
namespace console
{
const std::string message{"hello"};
void print(const std::string& text)
{
std::cout << text << std::endl;
}
}
using console::print; // includem doar funcția `print`
int main()
{
print(console::message); // trebuie să menționăm spațiul pentru `message`
}
Aici includem doar funcția print:
using console::print;
Prin urmare, pentru print nu este necesar să folosim numele spațiului, dar pentru celelalte componente da.
Pseudonime pentru spații de nume
Dacă numele unui spațiu de nume este prea lung, putem defini un alias:
namespace alias = nume_spatiu;
Exemplu:
#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); // accesăm `message` prin aliasul `mes`
}
În acest caz, pentru spațiul console::messages este definit pseudonimul mes.