Izjava uporaba imenskega prostora std na splošno velja za slabo prakso. Alternativa temu stavku je podajanje imenskega prostora, ki mu identifikator pripada, z uporabo operatorja področja (::) vsakič, ko deklariramo tip.
Čeprav nas izjava reši tipkanja std:: kadar koli želimo dostopati do razreda ali tipa, definiranega v imenskem prostoru std, uvozi celotno datoteko std imenski prostor v trenutni imenski prostor programa. Vzemimo nekaj primerov, da bomo razumeli, zakaj to morda ni tako dobra stvar
Recimo, da želimo uporabiti cout iz imenskega prostora std. Torej pišemo
Primer 1:
CPP
#include> using> namespace> std;> > cout <<>' Something to Display'>;> |
>
>
Zdaj, na poznejši stopnji razvoja, želimo uporabiti drugo različico cout, ki je implementirana po meri v neki knjižnici, imenovani foo (na primer)
CPP
#include> #include> using> namespace> std;> > cout <<>' Something to display'>;> |
>
>
Opazite, da obstaja dvoumnost, na katero knjižnico kaže cout? Prevajalnik lahko to zazna in ne prevede programa. V najslabšem primeru lahko program še vedno prevede, vendar pokliče napačno funkcijo, saj nikoli nismo določili, kateremu imenskemu prostoru identifikator pripada.
Imenski prostori so bili uvedeni v C++ za reševanje konfliktov imen identifikatorjev. To je zagotovilo, da imata lahko dva predmeta isto ime, a se ju obravnava različno, če pripadata različnim imenskim prostorom. Opazite, kako se je v tem primeru zgodilo ravno nasprotno. Namesto da bi rešili konflikt imena, dejansko ustvarimo konflikt imena.
Ko uvozimo imenski prostor, v bistvu potegnemo vse definicije tipov v trenutni obseg. Imenski prostor std je ogromen. Ima na stotine vnaprej določenih identifikatorjev, zato je možno, da razvijalec spregleda dejstvo, da obstaja druga definicija njihovega predvidenega predmeta v knjižnici std. Ne zavedajoč se tega, lahko nadaljujejo z določanjem lastne implementacije in pričakujejo, da bo uporabljena v kasnejših delih programa. Tako bi obstajali dve definiciji za isti tip v trenutnem imenskem prostoru. To v C++ ni dovoljeno in tudi če se program prevede, ni mogoče vedeti, katera definicija se kje uporablja.
Rešitev težave je eksplicitna določitev, kateremu imenskemu prostoru pripada naš identifikator z uporabo operatorja obsega (::). Tako je lahko ena od možnih rešitev zgornjega primera
CPP
#include> #include> > // Use cout of std library> std::cout <<>'Something to display'>;> > // Use cout of foo library> foo::cout <>'Something to display'>;> |
>
c++ gui
>
Toda tipkati je treba std:: vsakič, ko definiramo vrsto, je dolgočasno. Zaradi tega je naša koda videti bolj dlakasta zaradi številnih definicij tipov in otežuje branje kode. Upoštevajte na primer kodo za pridobivanje trenutnega časa v programu
Primer 2:
CPP
#include> #include> > auto> start = std::chrono::high_performance_clock::now()> > // Do Something> > auto> stop> >= std::chrono::high_peformance_clock::now();> auto> duration> >= std::duration_cast(stop - start);> |
>
>
Izvorne kode, ki je polna zapletenih in dolgih definicij tipov, ni lahko brati. Temu se razvijalci skušajo izogniti, saj jim je predvsem pomembna vzdržljivost kode.
Obstaja nekaj načinov za rešitev te dileme, tj. navedite natančen imenski prostor, ne da bi kodo zasipali s ključnimi besedami std.
Razmislite o uporabi typedefs
typedef nam prihrani pisanje dolgih definicij tipa. V našem primeru 1 bi lahko težavo rešili z uporabo dveh typedef, enega za knjižnico std in drugega za foo
CPP
c
#include> #include> > typedef> std::cout cout_std;> typedef> foo::cout cout_foo;> > cout_std <<>'Something to write'>;> cout_foo <<>'Something to write'>;> |
>
>
Namesto da uvažate celotne imenske prostore, uvozite skrajšani imenski prostor
V primeru 2 bi lahko uvozili samo imenski prostor chrono pod std.
CPP
#include> #include> > // Import only the chrono namespace under std> using> std::chrono;> > auto> start = high_performance_clock::now();> > // Do Something> auto> stop = high_performance_clock::now();> auto> duration duration_cast(stop - start);> |
>
>
Stavek lahko uporabimo tudi za uvoz posameznega identifikatorja. Za uvoz samo std::cout lahko uporabimo
using std::cout;>
Če še vedno uvažate celotne imenske prostore, poskusite to storiti znotraj funkcij ali omejenega obsega in ne v globalnem obsegu.
Uporabite stavek using namespace std znotraj definicij funkcij ali razredov, definicij struktur. Pri tem se definicije imenskega prostora uvozijo v lokalni obseg in vsaj vemo, od kod lahko izvirajo morebitne napake, če se pojavijo.
CPP
#include> > // Avoid this> using> namespace> std;> > void> foo()> {> >// Inside function> >// Use the import statement inside limited scope> >using> namespace> std;> > >// Proceed with function> }> |
>
>
Zaključek.
Razpravljali smo o alternativnih metodah za dostop do identifikatorja iz imenskega prostora. V vseh primerih se izogibajte uvozu celotnih imenskih prostorov v izvorno kodo.
Čeprav lahko traja nekaj časa, da se dobre prakse kodiranja naučijo in razvijejo, se na splošno izplačajo na dolgi rok. Pisanje čiste, nedvoumne in robustne kode brez napak bi moral biti namen vsakega razvijalca programiranja.