Niestety, przestrzenie nazw w C++ nie mają takiego wdzięku jak pakiety w Javie czy assemblies w .NET. Zwłaszcza w połączeniu z plikami nagłówkowymi potrafią one sprawić nieco problemów. Jeśli bowiem nie będziemy uważali, to możemy dość łatwo zniwelować korzyści, jakie płyną z ich używania.
Ale po kolei. Jeśli mamy do czynienia z modułem kodu (plikiem .cpp), to możemy bez żadnych skrupułów umieszczać w nim deklaracje using
lub using namespace
. Jeśli tylko nie prowadzi to do niejednoznaczności, wszystko jest w porządku, bowiem zasięg tych deklaracji ogranicza się tylko i wyłącznie do tego jednego pliku.
Gorzej jest niestety z plikami nagłówkowymi. Ponieważ włączane są one tu i ówdzie przy pomocy dyrektywy #include
, nie można tak po prostu wpisywać w nich deklaracji using namespace
. Zostałyby one bowiem rozpropagowane do wszystkich plików, które dany nagłówek włączają, efektywnie niwelując wszelkie korzyści zamknięcia fragmentów kodu w przestrzeń nazw. Bo co to za namespace, który wszyscy “rozpakowują” i przenoszą jego zawartość do przestrzeni globalnej?…
Dlatego nie ma rady: w plikach nagłówkowych można używać wyłącznie nazw kwalifikowanych – poprzedzonych wszystkimi nazwami przestrzeni, jak np. XC::Base::GC::BlockInfo
. W przeciwnym wypadku na pewno zaśmiecimy sobie którąś z przestrzeni (najczęściej globalną) identyfikatorami, które do niej nie należą – co będzie widoczne w systemach podpowiadania takich jak IntelliSense.
“w plikach nagłówkowych można używać wyłącznie nazw kwalifikowanych (…)”
Niekoniecznie. Alternatywną opcją np. w funkcjach inline może być lokalna deklaracja otwarcia danej przestrzeni, np.
Jest to oczywiście kwestia gustu, ale takie wyjście pozwala często uniknąć operatora zasięgu, jednocześnie nie “zaśmiecając” globalnej przestrzeni nazw.
Tak, ale to raczej wyjątek. W plikach nagłówkowych definiuje się głównie klasy, a w nich nie można zrobić:
(co swoją drogą jest dziwne).
A co z deklaracjami typu
using std::vector;
Czy to tez niweluje cały ficzer namespace?
Owszem, bo wtedy std::vector jest już dostępny poprzez nazwę niekwalifikowaną vector. Zaś
to odpowiednik:
W pierwszym przypadku zaśmiecasz nieumyślnie przestrzeń globalną jedną nazwą, a w drugim – wszystkimi nazwami z usingowanej przestrzeni.