Pochodzę z środowiska Java, w którym używane są pakiety, a nie przestrzenie nazw. Przyzwyczaiłem się do łączenia klas, które współpracują ze sobą, aby utworzyć kompletny obiekt w pakiety, a następnie ponownego ich używania z tego pakietu. Ale teraz pracuję w C ++.
Jak korzystasz z przestrzeni nazw w C ++? Czy tworzysz jedną przestrzeń nazw dla całej aplikacji, czy tworzysz przestrzenie nazw dla głównych komponentów? Jeśli tak, to w jaki sposób tworzysz obiekty z klas w innych przestrzeniach nazw?
źródło
std
przestrzeni nazw symbolami niżusing
w ogóle używania . Więc zawsze piszęstd::cout
lubstd::string
teraz, bo tak je teraz nazywam. Nigdy bym po prostu nie napisałcout
.std
, osobiście uważam, że jest to o wiele mniej ważne, gdy masz do czynienia z mniejszymi bibliotekami. Często możesz po prostu użyćusing namespace FooBario;
, szczególnie jeśli używasz znacznej liczby typów z biblioteki.using namespace X;
należy unikać plików nagłówkowych, jeśli to możliwe.mylibrary::endl
do reprezentowania mojej własnej specjalnej sekwencji nowego wiersza. To znaczy, po co wymyślać nazwy?Aby uniknąć mówienia wszystkiego Mark Ingram powiedział już małą wskazówkę dotyczącą korzystania z przestrzeni nazw:
Unikaj dyrektywy „używanie przestrzeni nazw” w plikach nagłówków - otwiera to przestrzeń nazw dla wszystkich części programu, które importują ten plik nagłówka. W plikach implementacyjnych (* .cpp) zwykle nie jest to duży problem - chociaż wolę używać dyrektywy „using namespace” na poziomie funkcji.
Myślę, że przestrzenie nazw są najczęściej używane w celu uniknięcia konfliktów nazw - niekoniecznie w celu uporządkowania struktury kodu. Organizowałbym programy C ++ głównie z plikami nagłówkowymi / strukturą plików.
Czasami przestrzenie nazw są używane w większych projektach C ++ do ukrywania szczegółów implementacji.
Uwaga dodatkowa do dyrektywy używającej: Niektóre osoby wolą używać „używania” tylko dla pojedynczych elementów:
źródło
using std::cout;
to deklaracja użyciausing std::cout, std::endl;
lub nawetusing std::cout, endl;
.using namespace x
w nagłówku, jeśli znajduje się on w innej przestrzeni nazw. Nie jest to coś, co ogólnie poleciłbym, ale nie zanieczyszcza globalnej przestrzeni nazw.Vincent Robert ma rację w swoim komentarzu Jak prawidłowo używać przestrzeni nazw w C ++? .
Korzystanie z przestrzeni nazw
Przestrzenie nazw są używane przynajmniej w celu uniknięcia kolizji nazw. W Javie jest to wymuszane przez idiom „org.domain” (ponieważ przypuszcza się, że nie użyje się niczego poza własną nazwą domeny).
W C ++ można nadać przestrzeń nazw dla całego kodu w module. Na przykład dla modułu MyModule.dll można nadać jego kodowi przestrzeń nazw MyModule. Widziałem gdzie indziej kogoś używającego MyCompany :: MyProject :: MyModule. Myślę, że to przesada, ale w sumie wydaje mi się to poprawne.
Za pomocą „za pomocą”
Używanie powinno być stosowane z dużą ostrożnością, ponieważ skutecznie importuje jeden (lub wszystkie) symbole z przestrzeni nazw do bieżącej przestrzeni nazw.
Złe jest to robić w pliku nagłówkowym, ponieważ nagłówek będzie skaził każde źródło, w tym (przypomina mi makra ...), a nawet w pliku źródłowym zły styl poza zakresem funkcji, ponieważ będzie importować w zakresie globalnym symbole z przestrzeni nazw.
Najbezpieczniejszym sposobem użycia „za pomocą” jest zaimportowanie wybranych symboli:
Zobaczysz wiele „za pomocą przestrzeni nazw std;” w samouczku lub przykładowych kodach. Powodem jest zmniejszenie liczby symboli, aby ułatwić czytanie, nie dlatego, że jest to dobry pomysł.
„using namespace std;” jest zniechęcany przez Scotta Meyersa (nie pamiętam dokładnie, która książka, ale w razie potrzeby mogę ją znaleźć).
Skład przestrzeni nazw
Przestrzenie nazw to więcej niż paczki. Kolejny przykład można znaleźć w „The C ++ Programming Language” Bjarne Stroustrup.
W „Edycji specjalnej”, w 8.2.8 Skład przestrzeni nazw , opisuje, w jaki sposób można połączyć dwie przestrzenie nazw AAA i BBB w inną zwaną CCC. W ten sposób CCC staje się aliasem zarówno dla AAA, jak i BBB:
Możesz nawet importować wybrane symbole z różnych przestrzeni nazw, aby zbudować własny interfejs przestrzeni nazw. Nie znalazłem jeszcze praktycznego zastosowania tego, ale teoretycznie jest fajnie.
źródło
Nie widziałem żadnej wzmianki o tym w innych odpowiedziach, więc oto moje 2 centy kanadyjskie:
W temacie „korzystanie z przestrzeni nazw” użyteczną instrukcją jest alias przestrzeni nazw, pozwalający na „zmianę nazwy” przestrzeni nazw, zwykle w celu nadania jej krótszej nazwy. Na przykład zamiast:
Możesz pisać:
źródło
Nie słuchaj każdego, kto mówi ci, że przestrzenie nazw to tylko przestrzenie nazw.
Są ważne, ponieważ kompilator uważa, że stosują zasadę interfejsu. Zasadniczo można to wyjaśnić przykładem:
Jeśli chcesz wydrukować obiekt A, kod będzie następujący:
Zauważ, że nie wspomnieliśmy jawnie o przestrzeni nazw podczas wywoływania funkcji. Oto zasada interfejsu: C ++ uważa funkcję przyjmującą typ za argument za część interfejsu tego typu, więc nie trzeba określać przestrzeni nazw, ponieważ parametr już implikował przestrzeń nazw.
Dlaczego ta zasada jest ważna? Wyobraź sobie, że autor klasy A nie udostępnił funkcji print () dla tej klasy. Musisz sam go dostarczyć. Ponieważ jesteś dobrym programistą, zdefiniujesz tę funkcję we własnej przestrzeni nazw, a może w globalnej przestrzeni nazw.
Twój kod może zacząć wywoływać funkcję print (a) w dowolnym miejscu. Teraz wyobraź sobie, że lata później autor decyduje się na udostępnienie funkcji print (), lepiej niż twoja, ponieważ zna elementy wewnętrzne swojej klasy i może stworzyć lepszą wersję niż twoja.
Następnie autorzy C ++ zdecydowali, że jego wersja funkcji print () powinna być używana zamiast tej podanej w innej przestrzeni nazw, aby przestrzegać zasady interfejsu. I że to „uaktualnienie” funkcji print () powinno być tak proste, jak to możliwe, co oznacza, że nie będziesz musiał zmieniać każdego wywołania funkcji print (). Dlatego „funkcje interfejsu” (funkcje w tej samej przestrzeni nazw co klasa) mogą być wywoływane bez określania przestrzeni nazw w C ++.
I dlatego powinieneś rozważyć przestrzeń nazw C ++ jako „interfejs”, kiedy z niej korzystasz i pamiętaj o zasadzie interfejsu.
Jeśli chcesz lepiej wyjaśnić to zachowanie, możesz odnieść się do książki Exceptional C ++ z Herb Sutter
źródło
W rzeczywistości boost wykorzystuje mnóstwo przestrzeni nazw, zwykle każda część boosta ma swoją własną przestrzeń nazw dla wewnętrznych działań, a następnie może umieścić tylko interfejs publiczny w boost przestrzeni nazw najwyższego poziomu.
Osobiście uważam, że im większa baza kodu, tym ważniejsze stają się przestrzenie nazw, nawet w obrębie jednej aplikacji (lub biblioteki). W pracy każdy moduł naszej aplikacji umieszczamy we własnej przestrzeni nazw.
Innym zastosowaniem (bez zamiaru słów) przestrzeni nazw, z których często korzystam, jest anonimowa przestrzeń nazw:
Jest to w zasadzie to samo, co:
Korzystanie z anonimowej przestrzeni nazw (zamiast statycznej) jest jednak zalecanym sposobem, aby kod i dane były widoczne tylko w bieżącej jednostce kompilacji w C ++.
źródło
const int CONSTANT = 42;
ponieważ const najwyższego poziomu w zakresie przestrzeni nazw już implikuje powiązanie wewnętrzne. W tym przypadku nie potrzebujesz anonimowej przestrzeni nazw.Pamiętaj też, że możesz dodać do przestrzeni nazw. To jest jaśniejsze na przykładzie, mam na myśli to, że możesz mieć:
w pliku
square.h
iw pliku
cube.h
. Definiuje to pojedynczą przestrzeń nazwMyNamespace
(to znaczy możesz zdefiniować jedną przestrzeń nazw dla wielu plików).źródło
W Javie:
W C ++:
I używając ich, Java:
I C ++:
Ponadto pełne nazwy to „somepackge.SomeClass” dla Java i „somenamespace :: SomeClass” dla C ++. Korzystając z tych konwencji, możesz organizować się tak, jak do tej pory jesteś przyzwyczajony w Javie, włączając w to tworzenie pasujących nazw folderów dla przestrzeni nazw. Nie ma jednak wymagań dotyczących folderów -> pakietów i plików -> klas, więc możesz nazwać swoje foldery i klasy niezależnie od pakietów i przestrzeni nazw.
źródło
@ marius
Tak, możesz używać jednocześnie kilku przestrzeni nazw, np .:
[Luty 2014 - (Czy to naprawdę trwało tak długo?): Ten konkretny przykład jest teraz niejednoznaczny, jak podkreśla Joey poniżej. Boost i std :: teraz mają teraz shared_ptr.]
źródło
std
równieżshared_ptr
teraz, więc przy użyciu zarównoboost
istd
nazw będzie kolidować podczas próby użyciashared_ptr
.Możesz również zawierać „za pomocą przestrzeni nazw ...” wewnątrz funkcji, na przykład:
źródło
Ogólnie rzecz biorąc, tworzę przestrzeń nazw dla części kodu, jeśli uważam, że może wystąpić konflikt nazw funkcji lub typu z innymi bibliotekami. Pomaga również znakować kod, ala boost :: .
źródło
Wolę korzystać z przestrzeni nazw najwyższego poziomu dla aplikacji i podkategorii dla komponentów.
Sposób, w jaki możesz korzystać z klas z innych przestrzeni nazw, jest zaskakująco bardzo podobny do sposobu w java. Możesz albo użyć „use NAMESPACE”, który jest podobny do instrukcji „import PACKAGE”, np. Użyj std. Lub określasz pakiet jako przedrostek klasy oddzielony znakiem „::”, np. Std :: string. Jest to podobne do „java.lang.String” w Javie.
źródło
Zauważ, że przestrzeń nazw w C ++ to tak naprawdę przestrzeń nazw. Nie zapewniają żadnej enkapsulacji wykonywanej przez pakiety w Javie, więc prawdopodobnie nie będziesz ich używać tak często.
źródło
Używałem przestrzeni nazw C ++ w taki sam sposób, jak w C #, Perl itp. Jest to tylko semantyczna separacja symboli między standardowymi bibliotekami, plikami stron trzecich i własnym kodem. Umieściłbym własną aplikację w jednej przestrzeni nazw, a następnie komponent biblioteki wielokrotnego użytku w innej przestrzeni nazw w celu rozdzielenia.
źródło
Inną różnicą między Javą a C ++ jest to, że w C ++ hierarchia przestrzeni nazw nie musi modyfikować układu systemu plików. Dlatego staram się umieszczać całą bibliotekę wielokrotnego użytku w pojedynczej przestrzeni nazw, a podsystemy w bibliotece w podkatalogach:
Podsystemy umieściłbym w zagnieżdżonych przestrzeniach nazw tylko wtedy, gdyby istniała możliwość konfliktu nazw.
źródło