We wszystkich naszych kursach języka c ++ wszyscy nauczyciele zawsze umieszczają w swoich plikach using namespace std;
zaraz po #include
znaku s .h
. Wydaje mi się to niebezpieczne, ponieważ wtedy dołączając ten nagłówek do innego programu, uzyskam przestrzeń nazw zaimportowaną do mojego programu, być może nie zdając sobie z tego sprawy, nie zamierzając jej lub nie chcąc (dołączanie nagłówka może być bardzo głęboko zagnieżdżone).
Więc moje pytanie jest podwójne: czy mam rację, że using namespace
nie powinno się tego używać w plikach nagłówkowych i / lub czy jest jakiś sposób, aby to cofnąć, na przykład:
//header.h
using namespace std {
.
.
.
}
Jeszcze jedno pytanie w tych samych wierszach: czy plik nagłówkowy powinien zawierać #include
wszystkie nagłówki, których .cpp
potrzebuje odpowiadający mu plik, tylko te, które są potrzebne do definicji nagłówków, i pozostawić resztę .cpp
pliku #include
, czy też nie zadeklarować wszystkiego, czego potrzebuje extern
?
Uzasadnienie pytania jest takie samo jak powyżej: nie chcę niespodzianek, gdy włączam.h
plików.
Poza tym, jeśli mam rację, czy jest to częsty błąd? Mam na myśli programowanie w świecie rzeczywistym i „rzeczywiste” projekty.
Dziękuję Ci.
źródło
using namespace
instrukcji, możesz użyć w pełni kwalifikowanej nazwy, aby rozwiązać problem.Odpowiedzi:
Zdecydowanie NIE powinieneś używać
using namespace
w nagłówkach dokładnie z powodu, dla którego mówisz, że może to nieoczekiwanie zmienić znaczenie kodu w innych plikach, które zawierają ten nagłówek. Nie ma sposobu, aby cofnąć,using namespace
co jest kolejnym powodem, dla którego jest tak niebezpieczny. Zwykle używamgrep
lub podobnego, aby upewnić się, żeusing namespace
nie jest to wywoływane w nagłówkach, zamiast próbować czegoś bardziej skomplikowanego. Prawdopodobnie statyczne kontrolery kodu również to zaznaczają.Nagłówek powinien zawierać tylko te nagłówki, które ma zostać skompilowane. Łatwym sposobem na wymuszenie tego jest zawsze dołączanie własnego nagłówka każdego pliku źródłowego jako pierwszej rzeczy, przed innymi nagłówkami. Wówczas kompilacja pliku źródłowego nie powiedzie się, jeśli nagłówek nie jest samodzielny. W niektórych przypadkach, na przykład w odniesieniu do klas szczegółowych implementacji w bibliotece, możesz użyć deklaracji do przodu zamiast,
#include
ponieważ masz pełną kontrolę nad definicją takiej zadeklarowanej do przodu klasy.Nie jestem pewien, czy nazwałbym to powszechnym, ale na pewno pojawia się od czasu do czasu, zwykle napisany przez nowych programistów, którzy nie są świadomi negatywnych konsekwencji. Zwykle tylko niewielka edukacja na temat zagrożeń rozwiązuje wszelkie problemy, ponieważ jest stosunkowo łatwa do naprawienia.
źródło
using
wyciągów w naszych.cpp
plikach? te3rdPartyLib::BigClassName<3rdPartyLib::AnotherBigName,3rdPartyLib::AnotherBigName>::Iterator
są śmiercią dla palców.template
funkcje - które mają znajdować się w nagłówkach?typedefs
?using
instrukcji w.cpp
plikach bez większego problemu, ponieważ zakres będzie ograniczony tylko do tego pliku, ale nigdy nie rób tego przed#include
instrukcją. Jeśli chodzi o funkcje szablonów zdefiniowane w nagłówkach, niestety nie znam dobrego rozwiązania poza wypisaniem przestrzeni nazw ... Być może mógłbyś umieścićusing
deklarację w oddzielnym zakresie{ /* using statement in between brackets */ }
, co przynajmniej uniemożliwiłoby jej ucieczkę z bieżącego pliku .Pozycja 59 w „Standardach kodowania C ++: 101 reguł, wytycznych i najlepszych praktyk” Suttera i Alexandrescu :
Plik nagłówkowy jest gościem w co najmniej jednym pliku źródłowym. Plik nagłówkowy zawierający
using
dyrektywy i deklaracje, przenosi również swoich awanturniczych znajomych.using
Deklaracja przynosi jednego kumpla.using
Dyrektywa przynosi we wszystkich kumpli w obszarze nazw. Korzystanie zusing namespace std;
jest dyrektywą używającą.Mówiąc poważnie, mamy przestrzenie nazw, aby uniknąć kolizji nazw. Plik nagłówkowy ma zapewnić interfejs. Większość nagłówków jest niezależna od tego, jaki kod może je zawierać, teraz lub w przyszłości. Dodanie
using
instrukcji w nagłówku dla wygody wewnętrznej narzuca te wygodne nazwy wszystkim potencjalnym klientom tego nagłówka. Może to doprowadzić do konfliktu nazw. I to jest po prostu niegrzeczne.źródło
Musisz zachować ostrożność, umieszczając nagłówki w nagłówkach. W dużych projektach może stworzyć bardzo splątany łańcuch zależności, który wyzwala większe / dłuższe przebudowy, niż było to faktycznie konieczne. Zapoznaj się z tym artykułem i jego dalszymi działaniami, aby dowiedzieć się więcej o znaczeniu dobrej struktury fizycznej w projektach C ++.
Powinieneś umieszczać nagłówki wewnątrz nagłówka tylko wtedy, gdy jest to absolutnie konieczne (gdy potrzebna jest pełna definicja klasy) i używać deklaracji do przodu, gdziekolwiek możesz (gdy klasa jest wymagana, to wskaźnik lub odwołanie).
Jeśli chodzi o przestrzenie nazw, zwykle używam jawnego zakresu przestrzeni nazw w moich plikach nagłówkowych i umieszczam tylko
using namespace
w moich plikach cpp.źródło
template
deklarację funkcji? to musi się pojawić w nagłówku, nie?Sprawdź standardy kodowania Goddard Space Flight Center (dla C i C ++). Okazuje się, że jest to trochę trudniejsze niż kiedyś - zobacz zaktualizowane odpowiedzi na pytania SO:
Standard kodowania GSFC C ++ mówi:
Pierwsze z pytań odsyłających zawiera teraz cytat ze standardu kodowania GSFC C i uzasadnienie, ale ostatecznie substancja jest taka sama.
źródło
Masz rację, że
using namespace
nagłówek jest niebezpieczny. Nie wiem, jak to cofnąć. Łatwo go wykryć, ale po prostu wyszukajusing namespace
w plikach nagłówkowych. Z tego ostatniego powodu jest to rzadkie w prawdziwych projektach. Bardziej doświadczeni współpracownicy wkrótce będą narzekać, jeśli ktoś zrobi coś takiego.W prawdziwych projektach ludzie starają się zminimalizować ilość dołączanych plików, ponieważ im mniej włączysz, tym szybciej się kompiluje. To oszczędza czas wszystkim. Jeśli jednak plik nagłówkowy zakłada, że coś powinno być zawarte przed nim, to powinien zawierać to samo. W przeciwnym razie powoduje, że nagłówki nie są samodzielne.
źródło
Masz rację. Każdy plik powinien zawierać tylko nagłówki wymagane przez ten plik. Jeśli chodzi o „czy robienie rzeczy źle jest powszechne w rzeczywistych projektach?” - o tak!
źródło
Jak wszystko w programowaniu, pragmatyzm powinien wygrać z dogmatyzmem, IMO.
Tak długo, jak podejmujesz decyzję dla całego projektu („Nasz projekt intensywnie używa STL i nie chcemy poprzedzać wszystkiego std ::.”), Nie widzę z tym problemu. Jedyne, co ryzykujesz, to w końcu kolizje nazw, a przy wszechobecności STL jest mało prawdopodobne, aby stanowił problem.
Z drugiej strony, gdyby była to decyzja jednego programisty w jednym (nieprywatnym) pliku nagłówkowym, widzę, jak spowodowałaby to zamieszanie w zespole i należy jej unikać.
źródło
W odniesieniu do „Czy jest jakiś sposób na cofnięcie [a
using
deklaracji]?”Myślę, że warto zaznaczyć, że na
using
deklaracje ma wpływ zakres.Tak skutecznie, tak. Ograniczając zakres
using
deklaracji, jej skutek trwa tylko w tym zakresie; jest „cofnięte”, gdy kończy się ten zakres.Gdy
using
deklaracja jest zadeklarowana w pliku poza jakimkolwiek innym zakresem, ma zasięg pliku i wpływa na wszystko w tym pliku.W przypadku pliku nagłówkowego, jeśli
using
deklaracja jest w zakresie pliku, będzie to dotyczyło zakresu dowolnego pliku, w którym znajduje się nagłówek.źródło
namespace
treść deklaracji) w porównaniu z tym, jak faktycznie działa (jak zmienna).{}
załączenie go ogranicza jego zakres,{}
po czym nie robi nic z nim związanego. To jest przypadkowy sposób, żeusing namespace
jest stosowany globalnie.Uważam, że możesz bezpiecznie używać `` using '' w nagłówkach C ++, jeśli piszesz swoje deklaracje w zagnieżdżonej przestrzeni nazw, takiej jak ta:
Powinno to obejmować tylko rzeczy zadeklarowane w „DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED” bez używanych przestrzeni nazw. Przetestowałem to na kompilatorze mingw64.
źródło
using
deklaracji wewnątrz definicji funkcji, gdzie mogę, aby nie zanieczyszczały przestrzeni nazw poza funkcją. Ale teraz chcę użyć literałów zdefiniowanych przez użytkownika C ++ 11 w pliku nagłówkowym i zgodnie ze zwykłą konwencją operatory literału są chronione przez przestrzeń nazw; ale nie chcę ich używać w listach inicjalizujących konstruktory, które nie są w zakresie, w którym mogę użyćusing
deklaracji niezanieczyszczającej . Więc to jest świetne do rozwiązania tego problemu.error: ... DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED:: DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED::ClassName ...
. Przynajmniej tak się dzieje ze mną w g ++.