2013-01-16 14 views
29

Czy to dobrze czy dobrze ćwiczyć używanie przestrzeni nazw jako klasy statycznej? Na przykład:Używanie przestrzeni nazw zamiast klasy statycznej w C++?

namespace MyStaticFunctions { 
    void doSomething(); 
} 

Versus:

class MyStaticFunctions { 
    static void doSomething(); 
} 
+0

wolę „extern”, ponieważ tylko C++ może zrobić coś takiego w OOP;) Również w przypadku zgodności z C lub Objective C. – 9dan

+3

* "Czy to dobrze czy dobrze ćwiczyć używanie przestrzeni nazw jako klasy statycznej" * - W rzeczywistości jest to znacznie lepsza praktyka niż twoja druga opcja. Ta ostatnia jest tylko preferowana (lub raczej potrzebna), jeśli potrzebujesz * "przestrzeni nazw szablonów" * lub chcesz, aby cały obszar nazw był przyjacielem innej klasy (choć może to być również wątpliwe). –

Odpowiedz

34

Nie ma czegoś takiego jak "klasa statyczna" w C++, więc z punktu widzenia C++ nie używasz jej "jako klasy statycznej", używasz jej "jako przestrzeni nazw". Z pewnością praktyką jest używanie przestrzeni nazw do wspólnego grupowania funkcji.

To zależy od ciebie, jak duże są grupy. Nie jest niczym niezwykłym, że biblioteki C++ używają pojedynczego obszaru nazw dla całego interfejsu publicznego. Może to zaskoczyć kogoś, kto jest przyzwyczajony do (powiedzmy) języka Java, gdzie klasy są często używane do grupowania mniejszej liczby metod statycznych. Ponieważ C++ był tutaj pierwszy, można powiedzieć, że Java używa klas jako przestrzeni nazw.

Tak więc, w C++ nie masz tendencji do oglądania klas podobnych do java.util.Collections lub java.lang.Math, pełnych statycznych elementów. Jeśli chcesz grupy takich funkcji w C++, użyj przestrzeni nazw.

Wyjątkiem (nie zawsze jest specjalny przypadek w C++?) Są typy cech, takie jak std::numeric_limits<T>, gdzie parametr szablonu powoduje, że klasa robi coś, czego nie może zrobić przestrzeń nazw. Można zdefiniować obszar nazw numeric_limits zawierający szablony funkcji max<T>(), min<T>() itp., Ale nie jest tak dobry. Po pierwsze, grupuje rzeczy nieco inaczej, typ T pojawia się "w dolnej części hierarchii". Po drugie, nie robi wszystkiego, co robi typ cech, ponieważ nie ma czegoś takiego jak "szablon obiektu", który pozwoliłby ci zdefiniować wartość numeric_limits::digits<T>.

Nie wiem, C# wystarczająco dobrze, aby wypowiedzieć się na temat praktycznych zastosowań klas statycznych tam, ale AFAIK to tylko klasa ograniczona do braku statycznych członków, więc jest to analogiczne do tych klas Java.

+1

+1 Innym przypadkiem, w którym może przydać się * "klasa statyczna" *, byłoby wykonanie całego obszaru nazw przyjacielem innej klasy (chociaż ten projekt może być w pierwszej kolejności wątpliwy, ale może czasem znacznie złagodzić). –

+4

Kolejny przypadek, w którym _namespaces_ jest lepszy. możesz użyć 'using namesspace MyStaticFunctions', jeśli zamierzasz używać więcej funkcji w funkcji – balki

4

To zależy.

Czy metoda jest logicznie powiązana z klasą? Jeśli tak, uczyń go członkiem, w przeciwnym razie umieść go w przestrzeni nazw.

Funkcjonalnie, są takie same, ale nie ma więcej funkcji niż funkcji, prawda? Rozważmy na przykład metodę, która zwraca nazwę klasy:

struct MyClass 
{ 
    static std::string getName() { return "MyClass"; } 
} 

Można oczywiście postawić metodę na zewnątrz, w namespace i uzyskać ten sam wynik, ale logicznie należy do klasy.

+1

Co to znaczy "logicznie związany z klasą"? –

+0

@AndyT: Cóż, jego logika jest silnie związana z klasą. –

21

W C++, w rzeczywistości zachęca się na poziomie języka, aby użyć namespace zamiast class zawierający tylko static metod powodu odnośnika Koeniga (aka Argument Dependent Lookup).

Przykład:

namespace geometry { 
    struct Point { int x, y; }; 

    double distance_from_center(Point const& p) { 
     return sqrt(p.x * p.x + p.y + p.y); 
    } 
} // namespace geometry 

int main() { 
    geometry::Point const p{3, 4}; // must qualify 

    std::cout << distance_from_center(p) << "\n"; // not qualified 
} 

Jeśli distance_from_center opisana jako metoda static w class, to trzeba jednoznacznie zakwalifikować go za każdym razem.

+1

Nigdy tego nie wiedziałem! jednak wyraźne sprawiłoby, że byłoby bardziej czytelne: – balki

+1

@balki: bardziej czytelne lub bardziej zagracone? To zawsze dobra równowaga. Dla użytkowników Java/C# może to być nieco oszałamiające, ale w języku C++ jest idiomatyczne, więc nie ma problemu. Ponadto w kodzie generycznym (szablony) jest to znacznie łatwiejsze. –

8

To trudne i ciekawe pytanie dla mnie osobiście, więc postanowiłem podzielić się moim skromnym zdaniem

Biorąc pod uwagę różnicę między „statycznym” klasy (tylko elementy statyczne) oraz nazw:

  1. przestrzeni nazw można być rozproszone na wielu plikach: dodatkowa elastyczność, ale powinna być stosowana ostrożnie.
  2. przestrzeń nazw zapewnia wyszukiwanie argumentów zależną (see Matthieu M. answer): przydatne w określonych sytuacjach
  3. „statyczne” klasa może mieć modyfikatory dostępu i może tworzyć hierarchię: Myślę, że członkowie prywatne zadeklarowane w interfejsie klasy i widoczny dla swoich klientów jest Funkcja C++ została podyktowana bardziej technicznymi, a nie logicznymi powodami. Nie widzę żadnych korzyści prywatnych członków statycznych. Członkowie chronieni za "statyczną" hierarchię? Nigdy żadnego nie widziałem.
  4. „statyczne” klasa może być „szablon”, oprócz członków szablonu: patrz Steve Jessop's answer na wielki przykład z STL

Z punktu widzenia technicznego widzenia, czasami trzeba podjąć decyzję klasy „static "(jak singleton), ale potem zmieniono wymagania i potrzebujesz wielu instancji. Klasa "statyczna" byłaby łatwiejsza do przekształcenia niż przestrzeń nazw.

I wreszcie, aby odpowiedzieć na pytanie:

jeśli nie potrzebują specjalnych cech „statyczne” klasy lub przestrzeni nazw, użyj tego, co lubisz bardziej :)

+0

Teraz rozpaczliwie chcę wymyślić użycie dla chronionego członka w klasie mającej tylko statycznych członków. Może jakaś sytuacja podobna do CRTP, gdzie klasa ma naturalnie szczególny związek z klasami pochodnymi? –

Powiązane problemy