namespace în C++

Grupează funcții, clase și variabile sub un nume comun, ca să nu se încurce cu alte nume identice din program sau din biblioteci.

Sintaxă
namespace nume {
    // declarații
}
namespace a::b { ... }      // C++17
namespace { ... }           // anonim
namespace alias = nume::lung;

Ce face namespace

Un namespace (spațiu de nume) este ca un dosar pentru nume. Tot ce declari în namespace magazin { ... } se folosește apoi ca magazin::nume. Biblioteca standard își ține totul în namespace std, de aici std::vector, std::string.

Două funcții cu același nume pot exista în spații de nume diferite fără conflict. Poți redeschide același namespace în mai multe fișiere; conținutul se adună.

Un spațiu de nume fără nume (namespace { ... }) face ca ce este înăuntru să fie vizibil doar în fișierul curent. Un alias (namespace fs = std::filesystem;) scurtează un nume lung.

Exemple

Exemplul 1: Același nume de funcție în două spații de nume

#include <print>

namespace magazin {
    double pret_final(double pret) { return pret * 1.21; }  // cu TVA
}

namespace angro {
    double pret_final(double pret) { return pret * 0.9; }   // cu reducere
}

int main() {
    std::println("Magazin: {:.2f} lei", magazin::pret_final(100));
    std::println("Angro: {:.2f} lei", angro::pret_final(100));
}

Rezultat

Magazin: 121.00 lei
Angro: 90.00 lei

Exemplul 2: Spații de nume imbricate și alias

Din C++17 poți scrie direct namespace firma::contabilitate în loc de două blocuri unul în altul. Aliasul cont scurtează numele.

#include <print>

namespace firma::contabilitate {
    int numar_facturi = 42;
}

namespace cont = firma::contabilitate;

int main() {
    std::println("Facturi: {}", firma::contabilitate::numar_facturi);
    cont::numar_facturi += 1;
    std::println("Facturi după încă una: {}", cont::numar_facturi);
}

Rezultat

Facturi: 42
Facturi după încă una: 43

Exemplul 3: Spațiu de nume anonim

Funcția ajutor este vizibilă doar în acest fișier. Alt fișier al programului poate avea propria funcție ajutor fără conflict la legare.

#include <print>
#include <string>

namespace {
    std::string ajutor() { return "folosită doar în acest fișier"; }
}

int main() {
    std::println("Funcția ajutor: {}", ajutor());
}

Rezultat

Funcția ajutor: folosită doar în acest fișier

Greșeli frecvente

  • Pui using namespace std; într-un fișier antet (.h). Toate fișierele care îl includ primesc toate numele din std, iar conflictele de nume devin greu de găsit.
  • Ai o funcție pret_final globală și una în magazin, apoi scrii using namespace magazin;. Apelul pret_final(100) devine ambiguu și nu se compilează; scrie prefixul magazin::.
  • Definești ceva în namespace std. Este interzis (cu mici excepții, ca specializarea lui std::hash) și duce la comportament nedefinit.

Comenzi înrudite

  • using: Aduce nume dintr-un spațiu de nume în locul curent sau creează un nume nou (alias) pentru un tip existent.
  • main: Funcția cu care începe orice program C++: sistemul o apelează la pornire, iar valoarea returnată spune dacă programul a reușit.
  • extern: Declară o variabilă sau funcție definită în altă parte (de obicei în alt fișier) sau cere legare în stilul limbajului C.
  • module, import, export: Modulele (C++20) înlocuiesc fișierele antet: un modul exportă ce vrea să fie vizibil, iar alt fișier îl folosește cu import.