GeeksforGeeks
On januari 16, 2022 by adminDe verklaring using namespace std wordt over het algemeen als een slechte gewoonte beschouwd. Het alternatief voor dit statement is om de namespace waartoe de identifier behoort te specificeren met de scope operator(::) elke keer dat we een type declareren.
Hoewel het statement ons bespaart van het typen van std:: wanneer we een klasse of type gedefinieerd in de std namespace willen benaderen, importeert het de gehele std namespace in de huidige namespace van het programma. Laat ons een paar voorbeelden nemen om te begrijpen waarom dit misschien niet zo’n goede zaak is
Laat ons zeggen dat we de cout uit de std namespace willen gebruiken. Dus schrijven we
Voorbeeld 1:
#include <iostream>
using
namespace
std;
cout <<
" Something to Display"
;
willen we een andere versie van cout gebruiken die op maat geïmplementeerd is in een bibliotheek genaamd “foo” (bijvoorbeeld)
#include <foo.h>
#include <iostream>
using
namespace
std;
cout <<
" Something to display"
;
Merk op dat er een ambiguïteit is, naar welke bibliotheek wijst cout? De compiler kan dit ontdekken en het programma niet compileren. In het ergste geval kan het programma nog steeds compileren, maar de verkeerde functie aanroepen, omdat we nooit hebben gespecificeerd tot welke namespace de identifier behoorde.
Namespaces werden in C++ geïntroduceerd om identifier naam conflicten op te lossen. Dit zorgde ervoor dat twee objecten dezelfde naam kunnen hebben en toch verschillend behandeld worden als ze tot verschillende namespaces behoren. Merk op hoe precies het tegenovergestelde is gebeurd in dit voorbeeld. In plaats van een naamconflict op te lossen, creëren we in feite een naamconflict.
Wanneer we een namespace importeren, trekken we in wezen alle type-definities in het huidige bereik. De std namespace is enorm. Het heeft honderden voorgedefinieerde identifiers, dus het is mogelijk dat een ontwikkelaar over het hoofd ziet dat er een andere definitie is van hun beoogde object in de std bibliotheek. Zich hiervan niet bewust kan hij zijn eigen implementatie specificeren en verwachten dat deze in latere delen van het programma gebruikt zal worden. Zo zouden er twee definities voor hetzelfde type bestaan in de huidige namespace. Dit is niet toegestaan in C++, en zelfs als het programma compileert is er geen manier om te weten welke definitie waar wordt gebruikt.
De oplossing voor het probleem is om expliciet aan te geven tot welke namespace onze identifier behoort met behulp van de scope operator (::). Een mogelijke oplossing voor bovenstaand voorbeeld is dus
#include <foo>
#include <iostream>
std::cout <<
"Something to display"
;
foo::cout <
"Something to display"
;
Maar het moeten typen van std:: elke keer dat we een type definiëren is vervelend. Het maakt onze code ook hariger met veel type-definities en maakt het moeilijk om de code te lezen. Beschouw bijvoorbeeld de code voor het verkrijgen van de huidige tijd in het programma
Voorbeeld 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);
De broncode die bezaaid is met ingewikkelde en lange typedefinities is niet erg gemakkelijk te lezen. Er zijn een paar manieren om dit dilemma op te lossen, d.w.z. de exacte namespace specificeren zonder de code vol te proppen met std keywords.
Overweeg het gebruik van typedefs
Typedefs besparen ons het schrijven van lange type-definities. In ons voorbeeld 1, zouden we het probleem kunnen oplossen door twee typedefs te gebruiken, een voor std library en een andere voor 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"
;
In plaats van hele namespaces te importeren, importeer een afgeknotte naamruimte
In voorbeeld 2 hadden we alleen de chrono naamruimte onder std kunnen importeren.
#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);
We kunnen het statement ook gebruiken voor het importeren van een enkele identifier. Om alleen std::cout te importeren zouden we
using std::cout;
Als je toch hele namespaces importeert, probeer dit dan te doen binnen functies of beperkte reikwijdte en niet in globale reikwijdte.
Gebruik het “using namespace std” statement binnen functie definities of klasse, struct definities. Op die manier worden de namespace-definities geïmporteerd in een lokaal bereik, en weten we tenminste waar mogelijke fouten vandaan kunnen komen als ze zich voordoen.
#include <isotream>
using
namespace
std;
void
foo()
{
using
namespace
std;
}
Conclusie.
We hebben alternatieve methoden besproken om toegang te krijgen tot een identifier vanuit een namespace. Vermijd in alle gevallen het importeren van volledige namespaces in de broncode.
Hoewel het aanleren en ontwikkelen van goede codeerpraktijken enige tijd kan kosten, betalen ze zich op de lange termijn over het algemeen terug. Het schrijven van schone, ondubbelzinnige en robuuste foutloze code zou de intentie moeten zijn van elke programmeur.
Geef een antwoord