Curs C++ | Sectiunea 29 – Name spaces
Un name space reprezinta un spatiu in care un anumit nume are un sens clar si lipsit de ambiguitate. Acum sa aplicam acest lucru la programarea noastra.
💡 Putem spune ca folosim aceste name space-uri pentru a ne organiza codul in grupuri logice. Evitam astfel posibilele coliziuni de nume ce pot aparea in momentul in care codul nostru este suficient de complex. Cum ar fi sa avem 2 functii diferite ce poarta acelasi nume.
Introducere
Sa incercam sa rulam urmatorul cod si sa vedem ce se va intampla:
❓ Vom observa urmatoarea eroare de compilare ‘cout’ was not declared in this scope; did you mean ‘std::cout’? . Dar de ce se intampla acest lucru, ce am uitat? Raspunsul se afla intr-o singura linie de cod:
😵 In momentul in care omitem aceasa linie, compilatorul devine dezorientat cand incercam sa folsim nume (de functii spre exemplu) fara a specifica de unde apartin acestea (pentru codul nostru fiind vorba de cout si endl).
💡 Putem totusi sa rezolvam aceasta problema si fara a folosi comanda using. Pentru a crea o conexiune intre numele dorit si name space-ul din care face parte folosim o sintaxa speciala :
📝 Name space-ul folosit in secventa noastra de cod poarta numele de std (venind de la standard). Sa incercam sa rescriem acum codul corespunzator. Nu va fi nimic nou, in decursul lectiilor am mai folosit aceasta sintaxa.
💡 Observam prezenta prefixului std in fata fiecarui functii folosite si un operator special “::“.Acesta poarta numele oficial de scope resolution operator. Are mai multe aplicatii, nu doar de a califica nume cu name space-urile corespunzatore dar vom vedea mai tarziu.
Definirea unui name space
Incepem aceasta notiune folosind un exemplu care poate nu are neaparat legatura cu programarea noastra dar ne va ajuta sa vizualizam mai bine.
🧙 Cu totii am vazut, sau macar am auzit de Stapanul Inelelor sau de Harry Potter. Stim ca in ambele lumi avem vrajitori puternici. Se pune problema, vrem sa ne referim la fiecare vrajitor din aceste lumi ca wizard, dar cum putem sa facem diferentierea intre ei? Nu putem avea 2 vrajitori cu acelasi nume.
🧉 Solutia pentru problema noastra va fi sa cream doua name space-uri diferite, cate unul pentru fiecare lume din care fac parte vrajitorii. Definirea unui name space se face folosind urmatoarea sintaxa:
Iar pentru cazul nostru specific, cu vrajitori, putem scrie astfel:
❗ Orice entitate declarata in interiorul unui name space va fi legata de acesta si ca urmare, va fi separata de orice alta entitate ce poarta acelasi nume.
🤼♂️ Bineinteles, intr-un caz real nu am folosi vrajitori. Cel mai probabil putem presupune ca 2 programatori au implementat, in mod independent diferite componente ale unui proiect complex. Nu putem garanta ca niciunul din cei 2 nu va refolosi nume alese de celalalt si invers.
In realiate, este si redundant si enervant sa verificam de fiecare data daca un nume este luat sau nu. Astfel ca este mai simplu ca toate entitatile sa fie legate de cate un name space, specific fiecarei componente, astfel rezolvand problema.
Folosirea unui name space
💡 Daca oricare din name space-urile disponibile este mai des folosit sau mai preferabil (acest lucru ramane la latitudinea fiecaruia si in functie de context), putem alege sa il folosim fara a-l mai califica. Acest lucru se realizata la fel cum am lucrat si cu std.
❗ Metoda de a folosi un namespace selectat se realizeaza prin instructiunea using. Daca instructiunea este plasata in afara unui block (reamintin ca un block reprezinta o parte de cod inscrisa in acolade {} ), va afecta tot codul urmator instructiunii, pana la terminarea fisierului sursa.
Exemplul de mai sus prezinta un caz in care folosin doua instructiuni using namespace. Prima ne permite, asa cum am invatat anterior, sa folosim cout si string, in mod convenabil, iar a doua declara ca orice wizard ce nu este calificat, face parte din middle_earth.
📝 Atentie, folosirea instructiunii using namespace nu trebuie sa conduca la situatii in care o entitate pare sa apartina mai multor name space-uri.
Prin urmare, folosind exemplul nostru, nu avem voie sa scrie urmatoarele doua instructiuni in acelasi block de cod.
Observam imediat o eroare ce ne evidentiaza acelasi lucru reference to ‘wizard’ is ambiguous.
💡 Daca folosim totusi, instructiunea using namespace in interiorul unui block, domeniul ei se termina odata cu block-ul.
- std este un name space global in acest caz
- hogwarts si middle_earth sunt name space-uri folosite selectiv, in interiorul unor block-uri de cod
Extinderea unui name space
💡 Am lucrat pana acum cu ideea ca un name space poate fi definit o singura data, insa acest lucru nu este adevarat. Avem posibilitatea sa extindem oricand un name space, de ori de cate ori ne dorim si in oricate fisiere sursa este nevoie.
In exemplul de mai sus, observam usurinta cu care am putut extinde name space-ul hogwarts adaugand noi entitati. Desi am declarat de 2 ori acelasi name space, acest proces poarta numele de extindere.
📝 Prima aparitie a unui name space poarta numele de name space original (original name space) iar urmatoarele aparitii poarta numele de extensie name space (extension name space).
Name space fara nume
💡 Avem posibilitatea sa definim un name space fara a-i specifica numele. Acesta poarta numele de name space anonim (anonymous namespace).
📝 Acest tip de name space este implicit si automat folosit in codul sursa unde definitiile sunt vizibile.
Vom observa ca am modificat exemplul nostru, lasand un name space anonim. Functionalitatea nu se va modifica, entitatile definite fiind in continuare vizibile.
❗ Atentie, nu puteti totusi sa aveti 2 name space-uri anonime ce definesc aceeasi entitate. Este echivalent cu a declara 2 variabile cu acelasi nume.
Redenumirea unui name space
💡 Se poate intampla ca un anumit name space pe care il avem sa aiba un nume poate prea lung, sau nu foarte descriptiv ori poate pur si simplu nu ne place 🙂 . Sintaxa este urmatoarea:
Noul nume poate fi folosit impreuna cu cel vechi. Deducem astfel ca redenumirea reprezinta de fapt un alias.
Aici se termina si aceasta sectiune. Daca aveti intrebari suplimentare puteti folosi informatiile de aici 🙂 .
➡ Sectiunea anterioara:Curs C++ | Sectiunea 28 – Strings (Last Words)
➡ Sectiunea urmatoare:Curs C++ | Sectiunea 30 – POO (Concepte de baza)

