GeeksforGeeks
On januari 16, 2022 by adminUttalandet using namespace std anses i allmänhet vara dålig praxis. Alternativet till detta uttalande är att ange det namnområde som identifieraren tillhör med hjälp av scope-operatorn(::) varje gång vi deklarerar en typ.
Och även om uttalandet gör att vi slipper skriva std:: när vi vill komma åt en klass eller typ som är definierad i std-namnområdet, importerar det hela std-namnområdet till programmets aktuella 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-namnområdet. Så vi skriver
Exempel 1:
#include <iostream>
using
namespace
std;
cout <<
" Something to Display"
;
Nu på ett senare utvecklingsstadium, vill vi använda en annan version av cout som är specialimplementerad i ett bibliotek som heter ”foo” (till exempel)
#include <foo.h>
#include <iostream>
using
namespace
std;
cout <<
" Something to display"
;
Märk hur det finns en tvetydighet, till vilket bibliotek pekar cout på? Kompilatorn kan upptäcka detta och inte kompilera programmet. I värsta fall kan programmet ändå kompileras men anropa fel funktion, eftersom vi aldrig angav vilket namnområde identifieraren tillhörde.
Namespaces infördes i C++ för att lösa konflikter mellan identifierarnamn. Detta säkerställde att två objekt kan ha samma namn och ändå behandlas olika om de tillhör olika namnområden. Lägg märke till hur den exakta motsatsen har inträffat i det här exemplet. Istället för att lösa en namnkonflikt skapar vi faktiskt en namnkonflikt.
När vi importerar ett namnområde drar vi i princip in alla typdefinitioner i det aktuella tillämpningsområdet. Namnsrummet std är enormt stort. Det har hundratals fördefinierade identifierare, så det är möjligt att en utvecklare förbiser det faktum att det finns en annan definition av deras avsedda objekt i std-biblioteket. Utan att vara medveten om detta kan han fortsätta att specificera sin egen implementation 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 kompileras finns det inget sätt att veta vilken definition som används var.
Lösningen på problemet är att explicit ange vilket namnområde vår identifierare tillhör med hjälp av scope-operatören (::). En möjlig lösning på ovanstående exempel kan alltså vara
#include <foo>
#include <iostream>
std::cout <<
"Something to display"
;
foo::cout <
"Something to display"
;
Men att behöva skriva std:: varje gång vi definierar en typ är tråkigt. Det gör också att vår kod ser hårdare ut med många typdefinitioner och gör det svårt att läsa koden. Tänk till exempel på koden för att få fram den aktuella tiden i programmet
Exempel 2:
.
#include <chrono>
#include <iostream>
auto
start = std::chrono::high_performance_clock::now()
auto
stop
= std::chrono::high_peformance_clock::now();
auto
duration
= std::duration_cast<std::chrono::milliseconds>(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 som utvecklare försöker undvika eftersom kodunderhållet är det viktigaste för dem.
Det finns några sätt att lösa detta dilemma, dvs. ange exakt namnområde utan att strö koden med std-nyckelord.
Överväg att använda typdefinitioner
Typdefinitioner besparar oss från att skriva långa typdefinitioner. I vårt exempel 1, kan vi lösa problemet genom att använda två typdefinitioner, en för std library och en för foo
#include <foo>
#include <iostream>
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 namnområden, importera ett avkortat namnområde
I exempel 2 kunde vi ha importerat endast namnområdet chrono under std.
#include <chrono>
#include <iostream>
using
std::chrono;
auto
start = high_performance_clock::now();
auto
stop = high_performance_clock::now();
auto
duration duration_cast<milliseconds>(stop - start);
Vi kan också använda uttalandet för att importera en enda identifierare. För att importera endast std::cout kan vi använda
using std::cout;
Om du ändå importerar hela namnområden, försök att göra det inom funktioner eller begränsad räckvidd och inte i global räckvidd.
Använd uttalandet ”using namespace std” inom funktionsdefinitioner eller klass-, struktdefinitioner. På så sätt importeras namnområdesdefinitionerna till en lokal räckvidd, och vi vet åtminstone var eventuella fel kan komma ifrån om de uppstår.
#include <isotream>
using
namespace
std;
void
foo()
{
using
namespace
std;
}
Slutsats.
Vi har diskuterat alternativa metoder för att få tillgång till en identifierare från ett namnområde. Undvik i alla fall att importera hela namnområden i källkoden.
Men även om goda kodningsmetoder kan ta lite tid att lära sig och utveckla, lönar de sig i allmänhet i längden. Att skriva ren, entydig och robust felfri kod bör vara avsikten för varje programmeringsutvecklare.
Lämna ett svar