Viele vernünftige Antworten schon. Ich werde mich mit einer Analogie befassen, die einigen Lesern helfen kann. ::
funktioniert ähnlich wie das Dateisystem-Verzeichnis-Trennzeichen ' /
', wenn Sie Ihren Pfad nach einem Programm durchsuchen, das Sie ausführen möchten. Erwägen:
/path/to/executable
Dies ist sehr explizit - nur eine ausführbare Datei an genau dieser Stelle im Dateisystembaum kann mit dieser Spezifikation übereinstimmen, unabhängig vom gültigen PATH. Ähnlich...
::std::cout
... ist im C ++ - Namespace "tree" gleichermaßen explizit.
Im Gegensatz zu solchen absoluten Pfaden können Sie gute UNIX-Shells (z. B. zsh ) konfigurieren , um relative Pfade unter Ihrem aktuellen Verzeichnis oder einem beliebigen Element in Ihrer PATH
Umgebungsvariablen aufzulösen. Wenn also PATH=/usr/bin:/usr/local/bin
und Sie "in" waren /tmp
, dann ...
X11/xterm
... würde gerne rennen, /tmp/X11/xterm
wenn gefunden, sonst /usr/bin/X11/xterm
, sonst /usr/local/bin/X11/xterm
. Angenommen, Sie befanden sich in einem Namespace namens X
und hatten ein " using namespace Y
" in Kraft, dann ...
std::cout
... könnte in einem gefunden werden ::X::std::cout
, ::std::cout
, ::Y::std::cout
und möglicherweise an anderen Orten aufgrund Argument abhängiger Lookup (ADL, auch bekannt als Koenig - Lookup). Es ist also nur ::std::cout
wirklich explizit, welches Objekt Sie genau meinen, aber zum Glück würde niemand, der bei klarem Verstand ist, jemals eine eigene Klasse / Struktur oder einen eigenen Namespace mit dem Namen " std
" oder etwas mit dem Namen " cout
" erstellen. In der Praxis std::cout
ist es also in Ordnung , nur zu verwenden .
Bemerkenswerte Unterschiede :
1) Shells verwenden in der Regel die erste Übereinstimmung mit der Reihenfolge in PATH
, während C ++ einen Compilerfehler ausgibt, wenn Sie mehrdeutig waren.
2) In C ++ Namen ohne führende Bereich kann in den aktuellen Namensraum angepasst werden, während die meisten UNIX - Shells nur das tun , wenn Sie setzen .
in der PATH
.
3) C ++ durchsucht immer den globalen Namespace (wie /
implizit Ihren PATH
).
Allgemeine Diskussion über Namespaces und Explizite von Symbolen
Die Verwendung absoluter ::abc::def::...
"Pfade" kann manchmal nützlich sein, um Sie von anderen Namespaces zu isolieren, die Sie verwenden, die Teil des Inhalts oder sogar anderer Bibliotheken sind, die der Clientcode Ihrer Bibliothek ebenfalls verwendet, aber nicht wirklich kontrolliert. Andererseits werden Sie auch enger an die vorhandene "absolute" Position des Symbols gekoppelt, und Sie vermissen die Vorteile des impliziten Abgleichs in Namespaces: weniger Kopplung, einfachere Mobilität des Codes zwischen Namespaces und präziserer, lesbarer Quellcode .
Wie bei vielen Dingen ist es ein Balanceakt. Die C ++ Standard - Puts vielen Kennungen unter , std::
dass weniger „einzigartig“ als cout
, dass Programmierer für etwas ganz anderes in ihrem Code verwenden kann (zB merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Zwei nicht verwandte Nicht-Standard-Bibliotheken haben eine weitaus höhere Wahrscheinlichkeit, dieselben Bezeichner zu verwenden, da sich die Autoren im Allgemeinen nicht oder weniger bewusst sind. Und Bibliotheken - einschließlich der C ++ Standard-Bibliothek - ändern ihre Symbole im Laufe der Zeit. All dies führt möglicherweise zu Mehrdeutigkeiten beim Neukompilieren von altem Code, insbesondere wenn using namespace
s häufig verwendet wird: Das Schlimmste, was Sie in diesem Bereich tun können, ist Zulassenusing namespace
s in Headern, um den Gültigkeitsbereichen der Header zu entgehen, sodass eine beliebig große Menge direkten und indirekten Client-Codes nicht in der Lage ist, selbst zu entscheiden, welche Namespaces verwendet werden sollen und wie Mehrdeutigkeiten verwaltet werden sollen.
Ein Leading ::
ist also ein Werkzeug in der Toolbox des C ++ - Programmierers, um einen bekannten Konflikt aktiv zu disambiguieren und / oder die Möglichkeit zukünftiger Mehrdeutigkeiten auszuschließen.
::
bezieht sich das nackte Mittel auf die Variable aus dem globalen / anonymen Namespace.