Wiele rozsądnych odpowiedzi już. Wprowadzę analogię, która może pomóc niektórym czytelnikom. ::
działa bardzo podobnie do separatora katalogów systemu plików ' /
' podczas wyszukiwania ścieżki w poszukiwaniu programu, który chcesz uruchomić. Rozważać:
/path/to/executable
Jest to bardzo wyraźne - tylko plik wykonywalny w tej dokładnej lokalizacji w drzewie systemu plików może pasować do tej specyfikacji, niezależnie od obowiązującej PATH. Podobnie...
::std::cout
... jest równie wyraźne w „drzewie” przestrzeni nazw C ++.
Kontrastując z takimi ścieżkami bezwzględnymi, możesz skonfigurować dobre powłoki UNIX (np. Zsh ), aby rozpoznawać ścieżki względne w bieżącym katalogu lub dowolnym elemencie PATH
zmiennej środowiskowej, więc jeśli PATH=/usr/bin:/usr/local/bin
i byłeś „w” /tmp
, to ...
X11/xterm
... z radością uciekłby, /tmp/X11/xterm
gdyby został znaleziony /usr/bin/X11/xterm
, inaczej /usr/local/bin/X11/xterm
. Podobnie, powiedz, że byłeś w przestrzeni nazwanej X
i miałeś using namespace Y
efekt „ ”, a następnie ...
std::cout
... można znaleźć w każdym z ::X::std::cout
, ::std::cout
, ::Y::std::cout
i ewentualnie innych miejsc ze względu na odnośnika argumentu zależne (ADL, aka Koenig odnośników). Tak więc, tylko ::std::cout
jest naprawdę jasne, co dokładnie masz na myśli, ale na szczęście nikt przy zdrowych zmysłach nigdy nie stworzyłby własnej klasy / struktury lub przestrzeni nazw o nazwie „ std
”, ani niczego zwanego „ cout
”, więc w praktyce używanie tylko std::cout
jest w porządku.
Godne uwagi różnice :
1) powłoki zwykle używają pierwszego dopasowania przy użyciu kolejności PATH
, podczas gdy C ++ daje błąd kompilatora, gdy jesteś niejednoznaczny.
2) W C ++, nazwy bez jakiejkolwiek prowadzącej zakresie mogą być dopasowane w bieżącym obszarze nazw, podczas gdy większość muszle UNIX zrobić tylko, że jeśli umieścić .
w PATH
.
3) C ++ zawsze przeszukuje globalną przestrzeń nazw (np. /
Pośrednio twoją PATH
).
Ogólna dyskusja na temat przestrzeni nazw i jawności symboli
Używanie absolutnych ::abc::def::...
„ścieżek” może czasem być przydatne do odizolowania cię od innych używanych przestrzeni nazw, które są częścią, ale tak naprawdę nie mają kontroli nad zawartością, a nawet innymi bibliotekami, z których korzysta także kod klienta twojej biblioteki. Z drugiej strony, bardziej ciasno łączy się z istniejącą „bezwzględną” lokalizacją symbolu i brakuje ci zalet niejawnego dopasowywania w przestrzeniach nazw: mniej sprzężenia, łatwiejsza mobilność kodu między przestrzeniami nazw i bardziej zwięzły, czytelny kod źródłowy .
Jak w przypadku wielu rzeczy, jest to działanie równoważące. C ++ standard stawia wiele identyfikatorów pod std::
które są mniej „unikalne” niż cout
, że programiści mogą wykorzystać na coś zupełnie innego w kodzie (np merge
, includes
, fill
, generate
, exchange
, queue
, toupper
, max
). Dwie niepowiązane niestandardowe biblioteki mają znacznie większą szansę na użycie tych samych identyfikatorów, ponieważ autorzy są na ogół nieświadomi siebie nawzajem lub mniej. A biblioteki - w tym biblioteka C ++ Standard - z czasem zmieniają swoje symbole. Wszystko to potencjalnie tworzy dwuznaczność podczas ponownej kompilacji starego kodu, szczególnie gdy często używa się using namespace
s: najgorszą rzeczą, jaką możesz zrobić w tym miejscu, jest zezwolenieusing namespace
w nagłówkach, aby uciec przed zasięgami nagłówków, tak że arbitralnie duża ilość bezpośredniego i pośredniego kodu klienta nie jest w stanie podejmować własnych decyzji, których przestrzeni nazw użyć i jak zarządzać niejednoznacznościami.
Tak więc wiodącym ::
jest jedno narzędzie w zestawie narzędzi programisty C ++, które aktywnie ujednoznacznia znane zderzenie i / lub eliminuje możliwość niejasności w przyszłości ...
::
oznacza odwołanie do zmiennej z globalnej / anonimowej przestrzeni nazw.