Przestrzeń nazw klasy VERSUS, klasa OR ORAZ przestrzeń nazw? [Zamknięte]

Zarówno klasa, jak i przestrzeń nazw?

To pytanie dotyczy wzorca, z którego korzystam coraz częściej: Posiadanie zarówno klasy, jak i przestrzeni nazw dla pokrewnych pojęć. Myślę, że motywują to głównie artefakty języka C ++, ale nie do końca.

Przypuszczam, że pytanie na najwyższym poziomie brzmi: czy to dobry pomysł? Masz zarówno klasę, jak i przestrzeń nazw dla pokrewnych pojęć?

Pytanie niższego poziomu:

Jak najlepiej to zrobić?

Klasa zagnieżdżona w przestrzeni nazw ?:

namespace Foo_Namespace {
   class Foo_Class {
       ...
   };
}

Lub oddzielne, peer, klasa i przestrzeń nazw ?:

class Foo_Class {
    ...
};
namespace Foo_Namespace {
   // non-class free functions, etc.
}

Muszę przyznać, że skłaniam się ku zagnieżdżaniu klasy w przestrzeni nazw. Nawet jeśli prowadzi to do brzydkich imion. Ale nawet jeśli to zrobię, jakie konwencje nazewnictwa należy stosować:

Poniżej jest za długo, co prowadzi do naprawdę brzydkich nazw Foo_Namespace :: Foo_Class

namespace Foo_Namespace {
   class Foo_Class {
       ...
   };
}

Nie trzeba używać przyrostków ani wskaźników w nazwie:

namespace Foo {
   class Foo {
       ...
   };
}

Ale wtedy jestem niepewny, kiedy patrzę na Foo :: bar (), jeśli to jest wolny pasek funkcji w przestrzeni nazw :: Foo, tj. :: Foo :: bar (), lub funkcja składowa w klasie Foo w przestrzeni nazw :: Foo :: Foo :: bar ().

A nazwy takie jak :: Foo :: Foo :: bar nadal nie są, umm, ładne.

Obecnie robię

Nie trzeba używać przyrostków ani wskaźników w nazwie:

namespace Foo_ns {
   class Foo {
       ...
   };
}

głównie dlatego, że zazwyczaj tworzę klasę jako pierwszą, a potem zdaję sobie sprawę, że przestrzeń nazw będzie miła.

Zastanawiam się, czy powinienem przywrócić konwencję nazewnictwa, której nie używałem od lat: _c dla klasy, _ns dla przestrzeni nazw:

namespace Foo_ns {
   class Foo_c {
       ...
   };
}

Detale:

Nie powtórzę tego, co powiedziałem powyżej, ale dodam jeszcze trochę.

Najbardziej praktycznym powodem, dla którego znam przestrzeń nazw oprócz klasy, jest to, że możesz wykonywać deklaracje wolnych funkcji w przestrzeni nazw, ale nie możesz wysyłać deklaracji niektórych metod klasy. To znaczy. z klasą musisz zadeklarować wszystko lub nic. Podczas gdy w przypadku wolnych funkcji w ogóle, a wolnych funkcji w przestrzeniach nazw w szczególności, można zadeklarować to jako fragmentaryczne. Części można zadeklarować w różnych plikach nagłówkowych. Zamiast #laczyć masywną bibliotekę z nagłówkiem tylko dla ogromnej klasy, możesz użyć deklaracji do przodu tylko dla jednej lub dwóch funkcji. Itp.

(Patrz na przykładhttp://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Forward_Declarations, chociaż Google netly sprowadza się raczej do deklaracji naprzód niż do nagłówka.)

Innym powodem jest to, że przestrzeń nazw pozwala na zachowanie małej klasy.

Największą zaletą klasy jest to, że klasa może zostać przekazana do szablonu, podczas gdy przestrzeń nazw nie może być.

Wolę zagnieżdżać klasę w przestrzeni nazw, Foo_ns / Foo_ns :: Foo_c, niż mieć je jako peery Foo_ns / Foo_c, ponieważ często klasa potrzebuje klas pomocniczych, np. Foo_ns / Foo_ns :: Foo_c / Foo_ns :: Foo_Helper_c. Jeśli klasa i przestrzeń nazw są równorzędne, dziwne wydaje się posiadanie Foo_ns / Foo_c, ale Foo_ns :: Foo_Helper_c.

Lubię przestrzenie nazw, ponieważ zgadzam się z Andrei Alexandresciu:http://laser.inf.ethz.ch/2012/slides/Alexandrescu/1-C++%20course%20parts%201%20and%202.pdf

 Class methods vs. free functions

 • Conventional wisdom: methods are cool, free functions are so 1960s
 • Yet:
   ◦ Free functions improve encapsulation over methods
   ◦ Free functions may be more general
   ◦ Free functions decouple better
   ◦ Free functions support conversions on their left-hand argument

  Surprising fact #2

    Making a function a method should be
    your last, not first, choice

  (c) 2012– Andrei Alexandrescu. 32 / 59

Lepiej jest tworzyć darmowe funkcje niż metody w klasach.

Ale czasami trzeba po prostu używać klas - np. dla szablonów.

Mądra konwencja nazewnictwa

W przeszłości użyłem Foo_ns / Foo_ns :: Foo_c

Używam teraz Foo_ns / Foo_ns :: Foo

(Przy okazji, używam Class_Names_With_Underscores_and_Initial_Caps, a nie CamelCase.)

Jeśli ma to sens, mogę wymusić przyrostek _ns w przestrzeni nazw - np. gdzie przestrzeń nazw i klasy nie muszą mieć tej samej nazwy.

Nie lubię robić ich o tej samej nazwie. Rozważmy konstruktor klasy Foo w przestrzeni nazw foo:

:: Foo :: Foo :: Foo () vs :: Foo_ns :: Foo :: Foo ()

Ten ostatni nie jest dużo lepszy, ale jest nieco mniej mylący.

Myślę, że zazwyczaj tworzę klasę samodzielnie, bez zagnieżdżania jej w przestrzeni nazw. Prawdę mówiąc, prawdopodobnie dodam kilka metod statycznych, zanim zdam sobie sprawę, że klasa zagnieżdżona w przestrzeni nazw byłaby lepsza. Na tym etapie refaktorem może być ból, a czasami kończę się tworzeniem funkcji przekazujących, które przechodzą z klasy statycznej do wolnej funkcji w przestrzeni nazw, lub odwrotnie. To powoduje, że żałuję bota, który przeskakuje do klasy w przestrzeni nazw bezpośrednio od kroku 1.

Wniosek

Mój obecny BKM to Foo_ns / Foo_ns :: Foo, tj.

namespace Foo_ns {
   class Foo { 
   ...
   };
}

Byłbym wdzięczny za wszelkie sugestie, wszelkie ulepszenia.

A może po prostu zostałem złamany?

questionAnswers(3)

yourAnswerToTheQuestion