Påståendet använder namnutrymme std anses allmänt vara dålig praxis. Alternativet till denna sats är att specificera namnområdet som identifieraren tillhör med hjälp av scope-operatorn(::) varje gång vi deklarerar en typ.
Även om uttalandet räddar oss från att skriva std:: närhelst vi vill komma åt en klass eller typ definierad i std-namnrymden, importerar den hela std namnutrymme till programmets nuvarande namnområde. Låt oss ta några exempel för att förstå varför detta kanske inte är så bra
Låt oss säga att vi vill använda cout från std-namnutrymmet. Så vi skriver
Exempel 1:
CPP
#include> using> namespace> std;> > cout <<>' Something to Display'>;> |
>
>
Nu i ett senare utvecklingsskede vill vi använda en annan version av cout som är anpassad implementerad i något bibliotek som heter foo (till exempel)
CPP
#include> #include> using> namespace> std;> > cout <<>' Something to display'>;> |
>
>
Lägg märke till att det nu finns en tvetydighet, vilket bibliotek pekar cout på? Kompilatorn kan upptäcka detta och inte kompilera programmet. I värsta fall kan programmet fortfarande kompilera men anropa fel funktion, eftersom vi aldrig specificerat vilket namnområde identifieraren tillhörde.
Namnutrymmen introducerades i C++ för att lösa identifierarnamnkonflikter. Detta säkerställde att två objekt kan ha samma namn och ändå behandlas olika om de tillhörde olika namnområden. Lägg märke till hur raka motsatsen har inträffat i det här exemplet. Istället för att lösa en namnkonflikt skapar vi faktiskt en namnkonflikt.
rullhjulet fungerar inte
När vi importerar ett namnområde drar vi i princip alla typdefinitioner in i det aktuella omfånget. Std-namnutrymmet är enormt. Den har hundratals fördefinierade identifierare, så det är möjligt att en utvecklare kan förbise det faktum att det finns en annan definition av deras avsedda objekt i std-biblioteket. Omedvetna om detta kan de fortsätta att specificera sin egen implementering och förvänta sig att den kommer att användas i senare delar av programmet. Det skulle alltså finnas två definitioner för samma typ i det aktuella namnområdet. Detta är inte tillåtet i C++, och även om programmet kompilerar finns det inget sätt att veta vilken definition som används var.
Lösningen på problemet är att uttryckligen ange vilket namnområde vår identifierare tillhör med hjälp av scope-operatorn (::). En möjlig lösning på exemplet ovan kan alltså vara
CPP
#include> #include> > // Use cout of std library> std::cout <<>'Something to display'>;> > // Use cout of foo library> foo::cout <>'Something to display'>;> |
>
>
Men måste skriva std:: varje gång vi definierar en typ är tråkigt. Det gör också att vår kod ser hårigare ut med massor av typdefinitioner och gör det svårt att läsa koden. Tänk till exempel på koden för att få aktuell tid i programmet
Exempel 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);> |
>
>
Källkoden som är full av komplicerade och långa typdefinitioner är inte särskilt lätt att läsa. Detta är något utvecklare försöker undvika eftersom kodunderhåll är främst viktigt för dem.
Det finns några sätt att lösa detta dilemma, dvs ange exakt namnutrymme utan att skräpa kod med standard nyckelord.
Överväg att använda typedefs
typedefs räddar oss från att skriva långa typdefinitioner. I vårt exempel 1 kunde vi lösa problemet med två typdefs, en för std-bibliotek och en annan för foo
CPP
#include> #include> > typedef> std::cout cout_std;> typedef> foo::cout cout_foo;> > cout_std <<>'Something to write'>;> cout_foo <<>'Something to write'>;> |
>
>
Istället för att importera hela namnutrymmen, importera ett trunkerat namnområde
I exempel 2 kunde vi endast ha importerat chrono-namnområdet under 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);> |
>
>
Vi kan också använda satsen för att importera en enda identifierare. För att endast importera std::cout kunde vi använda
using std::cout;>
Om du fortfarande importerar hela namnutrymmen, försök att göra det inom funktioner eller begränsad räckvidd och inte i global räckvidd.
Använd användning av namnutrymme std-satsen i funktionsdefinitioner eller klass, struct-definitioner. Genom att göra så importeras namnutrymmesdefinitionerna till ett lokalt omfång, och vi vet åtminstone var eventuella fel kan uppstå om de uppstår.
CPP
#include> > // Avoid this> using> namespace> std;> > void> foo()> {> >// Inside function> >// Use the import statement inside limited scope> >using> namespace> std;> > >// Proceed with function> }> |
>
>
Slutsats.
Vi har diskuterat alternativa metoder för att komma åt en identifierare från ett namnområde. Undvik i alla fall att importera hela namnutrymmen till källkoden.
Även om bra kodningsmetoder kan ta lite tid att lära sig och utveckla, betalar de sig i allmänhet ut på lång sikt. Att skriva ren, entydig och robust felfri kod bör vara avsikten för alla programmeringsutvecklare.