Cand un program atinge anumite dimensiuni el este, in mod tipic, divizat in fragmente care sunt intretinute (dezvoltate) de persoane diferite. Programatorii C trebuie sa fie atenti sa nu utilizeze in mod accidental aceleasi nume de identificatori.

Standardul C++ a introdus in 1995 un mecanism de prevenire a unor astfel de coliziuni: cuvantul cheie namespace. Fiecare multime de definitii dintr-o librarie sau program este impachetat intr-un spatiu de nume; daca alte definitii au nume identic, dar sunt situate in alte spatii de nume, nu apare coliziune.

Libraria standard C++ este impachetata in spatiul de nume std. Directiva using expune toate elementele unui spatiu de nume in unitatea de traducere din care a fost apelata. De exemplu:


	using namespace std;	//neindicat! expunde toate numele din std!
Se indica folosirea declaratiei using:

	using std::cout;
Exemplul 1: O clasa vector poate poate aparea simultan intr-o librarie matematica si intr-o librarie de containere, rezultand conflict. Sunt in conflict, de asemenea, si functiile membru cu nume identic (de exemplu, functiile care supraincarca operatorii).

Exemplul 2:


		//file excelSoftCompany.h
		namespace excel{
			class string {/**/};
			class vector {/**/};
		}
		//file excelSoftCompany.cpp
		#include <string>
		#include "excelSoftCompany.h"
		int main(){
			using namespace excel;
			string s;       //spatiul de nume excel
			std::string s1; //spatiul de nume std
			return 0;
		}
Se observa proprietatea de nume complet calificat: spatiu::clasa::data_membru.
Unui nume de spatiu i se poate asocia un alias: namespace ESC = excel;

ALGORITMUL LUI KOENIG
Acest algoritm instruieste compilatorul sa cerceteze si spatiul de nume care contine tipul argumentului unei functii; este solutia standardizata care rezolva situatii de genul:


		namespace MINE{
			class C{/**/};
			void func(C);
		}
		MINE::C ob; //obiect global de tipul MINE::C
		int main(){
		func(ob);   //OK, MINE::func() a fost apelata, desi nu este expusa; de ce?
		return 0;
		}
Fara acest algoritm, un programator nu poate decat sa repete numele calificat al functiei sau sa utilizeze directiva using.
Exemplul 3:

		#include <iostream>
		using std::cout;
		int main(){
		cout << "hello";
		return 0;
		}
Operatorul supraincarcat << nu este membru al cout, ci functie friend in spatiul std. Fara algoritmul lui Koenig, ar trebui scris: std::operator<<(cout,"hello");!

Observatii:
1. Algoritmul este aplicat automat si nu poate fi blocat!
2. Rezolutia in spatiile de nume este rezolvata in mod static (la compilare), deci nu implica o suprasarcina la executie.

Exemplul 4:


		#include <iostream>
		namespace NS1{
		class B{/**/};
		void f(B b){cout << "a";};
		};
		void f(NS1::B b){cout << "b";};
		int main(){
		NS1::B ob;
		f(ob);
		return 0;
		}
Un compilator care respecta standardul raspunde la acest text sursa cu un mesaj de eroare deoarece exista ambiguitate (nu se poate decide care versiune a functiei f() se executa: cea globala sau cea din NS1, regasita automat de catre algoritmul lui Koenig). Un compilator ne-standard alege pur si simplu o versiune a lui f()!

Restrictii
Spatiul de nume standard std nu poate fi modificat cu declaratii aditionale! Se interzice supraincarcarea operatorilor new si delete intr-un spatiu de nume!


		char *pc; //global
		namespace A{
			void* operator new (std::size_t);
			void operator delete (void*);
			void f(){
				pc = new char('a'); //se utilizeaza A::new
			}
		}
		void g(){
			delete pc; // se apeleaza A::delete sau ::delete?
		}
Unii programatori pot considera ca trebuie sa se apeleze perechea lui A::new, A::delete; altii considera ca trebuie sa se apeleze operatorul standard delete deoarece A::delete nu este vizibil in g! Interzicand supraincarcarea operatorilor in interiorul spatiilor de nume, se evita astfel de ambiguitati.