GeeksforGeeks
On januar 16, 2022 by adminUdsagnet using namespace std anses generelt for at være dårlig praksis. Alternativet til denne erklæring er at angive det namespace, som identifikatoren tilhører, ved hjælp af scope-operatoren(::), hver gang vi erklærer en type.
Selv om erklæringen sparer os for at skrive std::, når vi ønsker at få adgang til en klasse eller type, der er defineret i std-navneområdet, importerer den hele std-navneområdet ind i programmets aktuelle navneområde. Lad os tage et par eksempler for at forstå, hvorfor dette måske ikke er en så god ting
Lad os sige, at vi ønsker at bruge cout fra std-namensrummet. Så vi skriver
Eksempel 1:
#include <iostream>
using
namespace
std;
cout <<
" Something to Display"
;
Nu på et senere udviklingsstadium, ønsker vi at bruge en anden version af cout, der er specialimplementeret i et bibliotek kaldet “foo” (for eksempel)
#include <foo.h>
#include <iostream>
using
namespace
std;
cout <<
" Something to display"
;
Bemærk, hvordan der er en tvetydighed, til hvilket bibliotek peger cout på? Compileren kan opdage dette og ikke kompilere programmet. I værste fald kan programmet stadig kompileres, men kalde den forkerte funktion, da vi aldrig har angivet, hvilket namespace identifikatoren tilhørte.
Namespaces blev indført i C++ for at løse konflikter mellem identifikatornavne. Dette sikrede, at to objekter kan have det samme navn og alligevel blive behandlet forskelligt, hvis de tilhørte forskellige namespaces. Bemærk, hvordan det stik modsatte er sket i dette eksempel. I stedet for at løse en navnekonflikt skaber vi faktisk en navnekonflikt.
Når vi importerer et namespace, trækker vi i det væsentlige alle typedefinitioner ind i det aktuelle scope. Navneområdet std er enormt stort. Det har hundredvis af foruddefinerede identifikatorer, så det er muligt, at en udvikler kan overse, at der findes en anden definition af deres ønskede objekt i std-biblioteket. Uden at være klar over dette kan han fortsætte med at specificere sin egen implementering og forvente, at den vil blive brugt i senere dele af programmet. Der vil således eksistere to definitioner for den samme type i det aktuelle namespace. Dette er ikke tilladt i C++, og selv hvis programmet kompileres, er der ingen mulighed for at vide, hvilken definition der anvendes hvor.
Løsningen på problemet er at angive eksplicit, hvilket namespace vores identifikator tilhører ved hjælp af scope-operatoren (::). En mulig løsning på ovenstående eksempel kan således være
#include <foo>
#include <iostream>
std::cout <<
"Something to display"
;
foo::cout <
"Something to display"
;
Men det at skulle skrive std:: : hver gang vi definerer en type er trættende. Det får også vores kode til at se mere behåret ud med masser af typedefinitioner og gør det svært at læse koden. Overvej f.eks. koden til at få det aktuelle klokkeslæt i programmet
Eksempel 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);
Kildekoden, der er oversået med komplicerede og lange typedefinitioner, er ikke særlig let at læse. Det er noget, som udviklere forsøger at undgå, da vedligeholdelsen af koden er det vigtigste for dem.
Der er et par måder at løse dette dilemma på, dvs. at angive nøjagtigt namespace uden at strø koden med std-keywords.
Og overvej at bruge typedefs
Typedefs sparer os for at skrive lange typedefinitioner. I vores eksempel 1, kunne vi løse problemet ved at bruge to typedefs, en for std-biblioteket og en anden for 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"
;
I stedet for at importere hele namespaces, importere et afkortet namespace
I eksempel 2 kunne vi have importeret kun chrono namespace 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 også bruge erklæringen til at importere en enkelt identifikator. For kun at importere std::cout kan vi bruge
using std::cout;
Hvis du stadig importerer hele navnerum, skal du forsøge at gøre det inden for funktioner eller begrænset omfang og ikke i globalt omfang.
Brug “using namespace std”-erklæringen inden for funktionsdefinitioner eller klasse-, struktdefinitioner. Derved bliver navnerumsdefinitionerne importeret i et lokalt omfang, og vi ved i det mindste, hvor eventuelle fejl kan stamme fra, hvis de opstår.
#include <isotream>
using
namespace
std;
void
foo()
{
using
namespace
std;
}
Konklusion.
Vi har diskuteret alternative metoder til at få adgang til en identifikator fra et namespace. Undgå i alle tilfælde at importere hele namespaces i kildekoden.
Selv om god kodningspraksis kan tage noget tid at lære og udvikle, betaler den sig generelt i det lange løb. At skrive ren, utvetydig og robust fejlfri kode bør være hensigten for enhver programmeringsudvikler.
Skriv et svar