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 PATHzmiennej środowiskowej, więc jeśli PATH=/usr/bin:/usr/local/bini byłeś „w” /tmp, to ...
X11/xterm
... z radością uciekłby, /tmp/X11/xtermgdyby został znaleziony /usr/bin/X11/xterm, inaczej /usr/local/bin/X11/xterm. Podobnie, powiedz, że byłeś w przestrzeni nazwanej Xi miałeś using namespace Yefekt „ ”, a następnie ...
std::cout
... można znaleźć w każdym z ::X::std::cout, ::std::cout, ::Y::std::couti ewentualnie innych miejsc ze względu na odnośnika argumentu zależne (ADL, aka Koenig odnośników). Tak więc, tylko ::std::coutjest 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::coutjest 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 namespaces: najgorszą rzeczą, jaką możesz zrobić w tym miejscu, jest zezwolenieusing namespacew 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.