Twierdzenie używając przestrzeni nazw std jest powszechnie uważana za złą praktykę. Alternatywą dla tej instrukcji jest określenie przestrzeni nazw, do której należy identyfikator, za pomocą operatora zakresu (::) za każdym razem, gdy deklarujemy typ.
Chociaż stwierdzenie oszczędza nam pisania standardowe:: ilekroć chcemy uzyskać dostęp do klasy lub typu zdefiniowanego w przestrzeni nazw std, importuje całość st namespace do bieżącej przestrzeni nazw programu. Weźmy kilka przykładów, aby zrozumieć, dlaczego może to nie być takie dobre
Powiedzmy, że chcemy użyć cout z przestrzeni nazw std. Więc piszemy
Przykład 1:
CPP
#include> using> namespace> std;> > cout <<>' Something to Display'>;> |
>
>
Teraz, na późniejszym etapie rozwoju, chcemy użyć innej wersji cout, która jest niestandardowo zaimplementowana w jakiejś bibliotece zwanej foo (na przykład)
CPP
#include> #include> using> namespace> std;> > cout <<>' Something to display'>;> |
>
>
Zauważ, że istnieje niejasność: na którą bibliotekę wskazuje cout? Kompilator może to wykryć i nie skompilować programu. W najgorszym przypadku program może się jeszcze skompilować, ale wywoła niewłaściwą funkcję, ponieważ nigdy nie określiliśmy, do której przestrzeni nazw należy identyfikator.
Przestrzenie nazw zostały wprowadzone do C++, aby rozwiązać konflikty nazw identyfikatorów. Dzięki temu dwa obiekty mogły mieć tę samą nazwę, a mimo to być traktowane odmiennie, jeśli należały do różnych przestrzeni nazw. Zwróć uwagę, że w tym przykładzie wydarzyło się coś zupełnie odwrotnego. Zamiast rozwiązywać konflikt nazw, w rzeczywistości tworzymy konflikt nazewnictwa.
Kiedy importujemy przestrzeń nazw, zasadniczo przeciągamy wszystkie definicje typów do bieżącego zakresu. Przestrzeń nazw std jest ogromna. Ma setki predefiniowanych identyfikatorów, więc możliwe jest, że programista przeoczy fakt, że w bibliotece std znajduje się inna definicja jego zamierzonego obiektu. Nieświadomi tego mogą przystąpić do określania własnej implementacji i oczekiwać, że zostanie ona wykorzystana w późniejszych częściach programu. Zatem w bieżącej przestrzeni nazw istniałyby dwie definicje tego samego typu. Nie jest to dozwolone w C++ i nawet jeśli program się kompiluje, nie ma możliwości sprawdzenia, która definicja jest gdzie używana.
Rozwiązaniem problemu jest jawne określenie, do której przestrzeni nazw należy nasz identyfikator, za pomocą operatora zasięgu (::). Zatem jednym z możliwych rozwiązań powyższego przykładu może być
Verilog zawsze
CPP
#include> #include> > // Use cout of std library> std::cout <<>'Something to display'>;> > // Use cout of foo library> foo::cout <>'Something to display'>;> |
>
>
Ale muszę pisać standardowe:: za każdym razem, gdy definiujemy typ, jest to uciążliwe. Sprawia to również, że nasz kod wygląda na bardziej włochaty z dużą ilością definicji typów i utrudnia odczytanie kodu. Rozważmy na przykład kod pobierający aktualny czas w programie
Przykład 2:
CPP
#include> #include> > auto> start = std::chrono::high_performance_clock::now()> > // Do Something> > auto> stop> >= std::chrono::high_peformance_clock::now();> auto> duration> >= std::duration_cast(stop - start);> |
>
>
Kod źródłowy zaśmiecony skomplikowanymi i długimi definicjami typów nie jest zbyt łatwy do odczytania. Jest to coś, czego programiści starają się unikać, ponieważ łatwość konserwacji kodu jest dla nich najważniejsza.
Istnieje kilka sposobów rozwiązania tego dylematu, np. określenie dokładnej przestrzeni nazw bez zaśmiecania kodu standardowymi słowami kluczowymi.
Rozważ użycie typedefs
typedefs oszczędzają nam pisania długich definicji typów. W naszym przykładzie 1 moglibyśmy rozwiązać problem używając dwóch typedefs, jednego dla biblioteki std i drugiego dla foo
CPP
sortowanie przez wstawianie
#include> #include> > typedef> std::cout cout_std;> typedef> foo::cout cout_foo;> > cout_std <<>'Something to write'>;> cout_foo <<>'Something to write'>;> |
>
>
Zamiast importować całe przestrzenie nazw, zaimportuj obciętą przestrzeń nazw
W przykładzie 2 mogliśmy zaimportować tylko przestrzeń nazw chrono do std.
CPP
#include> #include> > // Import only the chrono namespace under std> using> std::chrono;> > auto> start = high_performance_clock::now();> > // Do Something> auto> stop = high_performance_clock::now();> auto> duration duration_cast(stop - start);> |
>
>
Instrukcję możemy wykorzystać także do zaimportowania pojedynczego identyfikatora. Aby zaimportować tylko std::cout, moglibyśmy użyć
using std::cout;>
Jeśli nadal importujesz całe przestrzenie nazw, spróbuj to zrobić wewnątrz funkcji lub w ograniczonym zakresie, a nie w zasięgu globalnym.
Użyj instrukcji using namespace std wewnątrz definicji funkcji lub klasy, definicji struktur. Robiąc to, definicje przestrzeni nazw są importowane do zakresu lokalnego i przynajmniej wiemy, skąd mogą pochodzić ewentualne błędy, jeśli się pojawią.
CPP
#include> > // Avoid this> using> namespace> std;> > void> foo()> {> >// Inside function> >// Use the import statement inside limited scope> >using> namespace> std;> > >// Proceed with function> }> |
>
>
Wniosek.
Omówiliśmy alternatywne metody dostępu do identyfikatora z przestrzeni nazw. We wszystkich przypadkach należy unikać importowania całych przestrzeni nazw do kodu źródłowego.
Chociaż nauczenie się i rozwinięcie dobrych praktyk kodowania może zająć trochę czasu, zazwyczaj przynoszą one korzyści w dłuższej perspektywie. Zamiarem każdego programisty powinno być pisanie czystego, jednoznacznego i solidnego, wolnego od błędów kodu.
co to internet