Es gibt bereits viele vernünftige Antworten. Ich werde mich mit einer Analogie einbringen, die einigen Lesern helfen könnte. ::
funktioniert ähnlich wie das Dateisystem-Verzeichnistrennzeichen ' /
', wenn Sie Ihren Pfad nach einem Programm durchsuchen, das Sie ausführen möchten. Bedenken Sie:
/path/to/executable
Dies ist sehr eindeutig - nur eine ausführbare Datei an genau dieser Stelle im Dateisystem kann dieser Spezifikation entsprechen, unabhängig vom gültigen PATH. Ähnlich...
::std::cout
...ist im C++-Namensraum "tree" ebenso eindeutig.
Im Gegensatz zu solchen absoluten Pfaden können Sie gute UNIX-Shells (z. B. zsh ) aufzulösen relativ Pfade unter Ihrem aktuellen Verzeichnis oder jedes Element in Ihrem PATH
Umgebungsvariable, wenn also PATH=/usr/bin:/usr/local/bin
und Sie waren "dabei". /tmp
...dann...
X11/xterm
...würde mit Freude laufen /tmp/X11/xterm
wenn gefunden, sonst /usr/bin/X11/xterm
sonst /usr/local/bin/X11/xterm
. Ähnlich verhält es sich, wenn Sie sich in einem Namespace namens X
und hatte einen " using namespace Y
" in der Tat, dann...
std::cout
...könnte in einem der folgenden Bereiche zu finden sein ::X::std::cout
, ::std::cout
, ::Y::std::cout
und möglicherweise auch an anderen Orten aufgrund von argumentabhängiges Nachschlagen (ADL, auch bekannt als Koenig Lookup). Also, nur ::std::cout
ist wirklich eindeutig, welches Objekt Sie meinen, aber glücklicherweise würde niemand, der bei Verstand ist, jemals eine eigene Klasse/Struktur oder einen Namespace mit dem Namen " std
", noch etwas mit der Bezeichnung " cout
", so dass in der Praxis nur die Verwendung von std::cout
ist in Ordnung.
Bemerkenswerte Unterschiede :
1) Muscheln neigen dazu, den ersten Treffer zu verwenden, indem sie die Reihenfolge in PATH
während C++ bei Zweideutigkeit einen Compilerfehler ausgibt.
2) In C++ können Namen ohne führenden Scope im aktuellen Namespace gefunden werden, während die meisten UNIX-Shells dies nur tun, wenn Sie .
im PATH
.
3) C++ durchsucht immer den globalen Namespace (als ob man /
implizit Ihr PATH
).
Allgemeine Diskussion über Namensräume und Explizitheit von Symbolen
Verwendung absoluter ::abc::def::...
"Pfade" können manchmal nützlich sein, um Sie von anderen Namespaces zu isolieren, die Sie verwenden, von denen Sie Teil sind, über deren Inhalt Sie aber keine wirkliche Kontrolle haben, oder sogar von anderen Bibliotheken, die der Client-Code Ihrer Bibliothek ebenfalls verwendet. Andererseits sind Sie dadurch auch enger an die bestehende "absolute" Position des Symbols gebunden, und Sie verpassen die Vorteile des impliziten Abgleichs in Namespaces: weniger Kopplung, einfachere Mobilität des Codes zwischen Namespaces und prägnanterer, lesbarerer Quellcode.
Wie bei vielen anderen Dingen auch, ist es ein Balanceakt. Der C++ Standard stellt viele Bezeichner unter std::
die weniger "einzigartig" sind als cout
die Programmierer für etwas völlig anderes in ihrem Code verwenden könnten (z. B. merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Bei zwei nicht miteinander verbundenen Nicht-Standard-Bibliotheken ist die Wahrscheinlichkeit, dass sie dieselben Bezeichner verwenden, weitaus größer, da sich die Autoren in der Regel nicht oder weniger bewusst sind. Und Bibliotheken - einschließlich der C++-Standardbibliothek - ändern ihre Symbole im Laufe der Zeit. All dies kann beim Neukompilieren von altem Code zu Mehrdeutigkeit führen, insbesondere wenn die folgenden Symbole häufig verwendet wurden using namespace
s: Das Schlimmste, was man in diesem Bereich tun kann, ist zuzulassen, dass using namespace
s in Headern, um dem Geltungsbereich der Header zu entkommen, so dass eine beliebig große Menge an direktem und indirektem Client-Code nicht in der Lage ist, eigene Entscheidungen darüber zu treffen, welche Namespaces zu verwenden sind und wie mit Mehrdeutigkeiten umzugehen ist.
Also, eine führende ::
ist ein Werkzeug im Werkzeugkasten des C++-Programmierers, um einen bekannten Konflikt aktiv zu disambiguieren und/oder die Möglichkeit künftiger Mehrdeutigkeiten zu beseitigen....