Wyższość nienazwanej przestrzeni nazw nad statyczną?

Odpowiedzi:

136

Zasadniczo odnosisz się do sekcji §7.3.1.1 / 2 ze standardu C ++ 03,

Używanie słowa kluczowego static jest przestarzałe podczas deklarowania obiektów w zakresie przestrzeni nazw; nienazwana przestrzeń nazw stanowi lepszą alternatywę.

Zauważ, że ten akapit został już usunięty w C ++ 11. staticfunkcje są według standardu nie są już przestarzałe!

Niemniej jednak przestrzenie nazw bez nazw są lepsze od słowa kluczowego static, głównie dlatego, że słowo kluczowe staticma zastosowanie tylko do deklaracji zmiennych i funkcji, a nie do typów zdefiniowanych przez użytkownika .

Poniższy kod obowiązuje w C ++

   //legal code
   static int sample_function() { /* function body */ }
   static int sample_variable;

Ale ten kod NIE jest ważny:

   //illegal code
   static class sample_class { /* class body */ };
   static struct sample_struct { /* struct body */ };

Rozwiązaniem jest więc nienazwana-przestrzeń nazw, czyli

   //legal code
   namespace 
   {  
        class sample_class { /* class body */ };
        struct sample_struct { /* struct body */ };
   }

Mam nadzieję, że wyjaśnia, dlaczego unnamed-namespacejest lepszy od static.

Należy również zauważyć, że użycie słowa kluczowego static jest przestarzałe podczas deklarowania obiektów w zakresie przestrzeni nazw (zgodnie ze standardem).

Nawaz
źródło
12
Mówiąc bardziej ogólnie, nienazwana przestrzeń nazw umożliwia zewnętrzne połączenie. To właśnie umożliwia deklarację klasy jednostki lokalnej do translacji. Pozwala także np. Na użycie stałej łańcucha powiązania zewnętrznego jako argumentu szablonu.
Pozdrawiam i hth. - Alf
10
Jak zauważył Fred Nurk w innej odpowiedzi, wydaje się, że ta deprecateduwaga została usunięta z najnowszego C ++ 0x FCD (n3225).
Matthieu M.
37
Odpowiadasz na własne pytanie i dziękujesz sobie: -o
manpreet singh
12
Jaka byłaby różnica w porównaniu z samym zdefiniowaniem klasy w cpp (bez anonimowej przestrzeni nazw, bez statycznej)?
Luchian Grigore
6
@LuchianGrigore Problemy z łączeniem w przypadku 2 .cppto definiowanie klasy o tej samej nazwie.
Xaqq
9

Z tym wiąże się ciekawy problem:

Załóżmy, że używasz staticsłowa kluczowego lub nienazwanego, namespaceaby uczynić jakąś funkcję wewnętrzną w module (jednostka tłumaczenia), ponieważ ta funkcja jest przeznaczona do użytku wewnętrznego przez moduł i nie jest dostępna poza nim. (Nienazwane elementy namespacemają tę zaletę, że poza funkcjami definiują również dane i typy).

Z czasem plik źródłowy implementacji Twojego modułu się powiększa i chciałbyś podzielić go na kilka osobnych plików źródłowych, co pozwoliłoby na lepszą organizację kodu, szybsze znajdowanie definicji i samodzielną kompilację.

Ale teraz pojawia się problem: te funkcje nie mogą już dotyczyć staticmodułu, ponieważ statictak naprawdę nie odnoszą się do modułu , ale do pliku źródłowego (jednostki tłumaczeniowej). Jesteś zmuszony uczynić je niedozwolonymi, staticaby umożliwić dostęp do nich z innych części (plików obiektowych) tego modułu. Ale oznacza to również, że nie są już ukryte / prywatne dla modułu: mając zewnętrzne powiązania, można uzyskać do nich dostęp z innych modułów, co nie było Twoim pierwotnym zamiarem.

Bez nazwy też namespacenie rozwiązałoby tego problemu, ponieważ jest on również zdefiniowany dla konkretnego pliku źródłowego (jednostki tłumaczeniowej) i nie można uzyskać do niego dostępu z zewnątrz.

Byłoby wspaniale, gdyby można było określić, że pewne namespacejest private, że to, co określa się w nim, ma być używany wewnętrznie przez moduł do której należy. Ale oczywiście C ++ nie ma takiej koncepcji jak „moduły”, tylko „jednostki tłumaczeniowe”, które są ściśle powiązane z plikami źródłowymi.

SasQ
źródło
3
Byłoby to i tak hack i ograniczone rozwiązanie, ale możesz dołączyć plik (i) cpp z wewnętrznymi funkcjami statycznymi lub z przestrzenią nazw do swoich „głównych” plików cpp. Następnie wyklucz te pliki cpp „satelity” z kompilacji i gotowe. Jedyny problem, jeśli masz dwa lub więcej `` głównych '' plików cpp i oba chcą użyć tej fajnej funkcji z jednego z `` satelitarnych '' plików cpp ...
Sergey
czy używanie dziedziczenia z funkcjami prywatnymi / chronionymi / publicznymi z funkcjami statycznymi nie jest rozwiązaniem?
Ali
C ++ 20 wprowadza moduły, które rozwiązują Twój problem.
LF