Powiedzmy, że mam lub zamierzam napisać zestaw powiązanych funkcji. Powiedzmy, że są związane z matematyką. Pod względem organizacyjnym powinienem:
- Napisz te funkcje i umieść je w mojej
MyMath
przestrzeni nazw i odwołuj się do nich za pośrednictwemMyMath::XYZ()
- Utwórz klasę o nazwie
MyMath
i ustaw te metody statycznie i odwołuj się do nich podobnieMyMath::XYZ()
Dlaczego miałbym wybierać między sobą jako sposób organizacji mojego oprogramowania?
c++
namespaces
static-methods
RobertL
źródło
źródło
Odpowiedzi:
Domyślnie używaj funkcji z przestrzenią nazw.
Klasy mają budować obiekty, a nie zastępować przestrzenie nazw.
W kodzie obiektowym
Scott Meyers napisał cały artykuł do swojej książki Effective C ++ na ten temat: „Wolę funkcje nieprzyjazne od innych niż funkcje członkowskie”. Internetowe odniesienie do tej zasady znalazłem w artykule z Herb Sutter:http://www.gotw.ca/gotw/084.htm
Ważne jest, aby wiedzieć, że: W C ++ funkcje w tej samej przestrzeni nazw, w której klasa należy do interfejsu tej klasy (ponieważ ADL przeszuka te funkcje podczas rozwiązywania wywołań funkcji).
Funkcje z przestrzenią nazw, chyba że zostaną uznane za „przyjaciel”, nie mają dostępu do wewnętrznych elementów klasy, podczas gdy metody statyczne mają.
Oznacza to na przykład, że utrzymując klasę, jeśli chcesz zmienić elementy wewnętrzne swojej klasy, będziesz musiał szukać efektów ubocznych we wszystkich jej metodach, w tym statycznych.
Rozszerzenie I
Dodawanie kodu do interfejsu klasy.
W języku C # możesz dodawać metody do klasy, nawet jeśli nie masz do niej dostępu. Ale w C ++ jest to niemożliwe.
Ale nadal w C ++ możesz nadal dodawać funkcje przestrzeni nazw, nawet do klasy, którą ktoś dla ciebie napisał.
Patrz z drugiej strony, jest to ważne przy projektowaniu kodu, ponieważ umieszczając swoje funkcje w przestrzeni nazw, upoważnisz użytkowników do zwiększenia / ukończenia interfejsu klasy.
Rozszerzenie II
Efektem ubocznym poprzedniego punktu jest niemożliwość zadeklarowania metod statycznych w wielu nagłówkach. Każda metoda musi być zadeklarowana w tej samej klasie.
W przypadku przestrzeni nazw funkcje z tej samej przestrzeni nazw można zadeklarować w wielu nagłówkach (prawie standardowa funkcja zamiany jest tego najlepszym przykładem).
Rozszerzenie III
Podstawową zaletą przestrzeni nazw jest to, że w niektórych kodach można uniknąć wspominania o niej, jeśli użyjesz słowa kluczowego „using”:
Możesz nawet ograniczyć „zanieczyszczenie” do jednej klasy:
Ten „wzorzec” jest obowiązkowy dla właściwego użycia prawie standardowego idiomu zamiany.
Jest to niemożliwe w przypadku metod statycznych w klasach.
Przestrzenie nazw C ++ mają więc własną semantykę.
Ale idzie dalej, ponieważ można łączyć przestrzenie nazw w sposób podobny do dziedziczenia.
Na przykład, jeśli masz przestrzeń nazw A z funkcją AAA, przestrzeń nazw B z funkcją BBB, możesz zadeklarować przestrzeń nazw C i wprowadzić AAA i BBB w tej przestrzeni nazw za pomocą słowa kluczowego.
Wniosek
Przestrzenie nazw dotyczą przestrzeni nazw. Klasy są dla klas.
C ++ został zaprojektowany, więc każda koncepcja jest inna i jest używana w różnych przypadkach, w różnych przypadkach, jako rozwiązanie różnych problemów.
Nie używaj klas, gdy potrzebujesz przestrzeni nazw.
A w twoim przypadku potrzebujesz przestrzeni nazw.
źródło
Jest wielu ludzi, którzy nie zgadzają się ze mną, ale tak to widzę:
Klasa jest zasadniczo definicją pewnego rodzaju obiektu. Metody statyczne powinny definiować operacje ściśle związane z definicją obiektu.
Jeśli chcesz mieć grupę powiązanych funkcji niezwiązanych z obiektem bazowym lub definicją rodzaju obiektu , powiedziałbym, że idź z tylko przestrzenią nazw. Dla mnie, koncepcyjnie, jest to o wiele bardziej sensowne.
Na przykład w twoim przypadku zadaj sobie pytanie: „Co to jest MyMath?” Jeśli
MyMath
nie określa rodzaj obiektu, a ja powiedziałbym: nie sprawiają, że klasa.Ale tak jak powiedziałem, wiem, że jest wielu ludzi, którzy (nawet gwałtownie) nie zgadzają się ze mną w tej sprawie (w szczególności deweloperzy Java i C #).
źródło
typedef
je, użyć ich jako parametrów szablonów itp.W przeciwnym razie użyj funkcji z przestrzenią nazw.
W odpowiedzi na komentarze: tak, metody statyczne i dane statyczne są zwykle nadmiernie wykorzystywane. Dlatego zaproponowałem tylko dwa powiązane scenariusze, w których moim zdaniem mogą być pomocne. W konkretnym przykładzie PO (zestaw procedur matematycznych), jeśli chciałby możliwości określenia parametrów - powiedzmy, podstawowego typu danych i precyzji wyjściowej - które miałyby zastosowanie do wszystkich procedur, mógłby zrobić coś takiego:
Jeśli nie musisz, wtedy przez wszystkich środków używać nazw.
źródło
template
argumentów!Powinieneś użyć przestrzeni nazw, ponieważ przestrzeń nazw ma wiele zalet w stosunku do klasy:
using
członka klasy; możesz byćusing
członkiem przestrzeni nazwusing class
, choćusing namespace
nie jest to często dobry pomysłMoim zdaniem członkowie statyczni są bardzo nadużywani. W większości przypadków nie są one koniecznością. Funkcje elementów statycznych są prawdopodobnie lepsze niż funkcje zakresu plików, a elementy danych statycznych to tylko obiekty globalne o lepszej, niezasłużonej reputacji.
źródło
inline
słowa kluczowego, aby spełnić wymagania ODR.inline
, a NIE jest to „wstawianie” treści funkcji. Rzeczywistym (i gwarantowane przez standard) Celeminline
jest, aby uniknąć tworzenia definicji. Przeczytaj o „Zasadzie jednej definicji” dla C ++. Ponadto połączone pytanie SO nie zostało skompilowane z powodu problemów ze wstępnie skompilowanym nagłówkiem zamiast problemów z ODR.Wolałbym przestrzenie nazw, w ten sposób możesz mieć prywatne dane w anonimowej przestrzeni nazw w pliku implementacji (więc nie musi wcale pojawiać się w nagłówku, w przeciwieństwie do
private
członków). Kolejną korzyścią jest to, że dziękiusing
przestrzeni nazw klienci metod mogą zrezygnować z określaniaMyMath::
źródło
Jeszcze jeden powód, aby używać klasy - Opcja korzystania ze specyfikatorów dostępu. Następnie możesz ewentualnie podzielić swoją publiczną metodę statyczną na mniejsze metody prywatne. Metoda publiczna może wywoływać wiele metod prywatnych.
źródło
private
metoda jest bardziej dostępna niż metoda, której prototyp nie jest w ogóle opublikowany w nagłówku (a zatem pozostaje niewidoczny). Nie wspominam nawet o lepszej enkapsulacji oferowanej przez anonimowe funkcje przestrzeni nazw..cpp
pliku, co uczyniłoby to prywatnym dla tej jednostki tłumaczeniowej bez podawania zbędnych informacji osobom czytającym plik nagłówkowy. Skutecznie staram się opowiadać za idiomem PIMPL..cpp
pliku, jeśli chcesz używać szablonów.Zarówno przestrzeń nazw, jak i metoda klasy mają swoje zastosowania. Przestrzeń nazw może być rozłożona na pliki, ale jest to słabość, jeśli trzeba wymusić cały powiązany kod, aby przejść do jednego pliku. Jak wspomniano powyżej klasa pozwala również tworzyć prywatne statyczne elementy w klasie. Możesz mieć go w anonimowej przestrzeni nazw pliku implementacji, jednak nadal jest to większy zakres niż posiadanie ich w klasie.
źródło
private:
te. a w wielu przypadkach, gdy wydaje się, że wymagany jest uprzywilejowany dostęp , można to uwzględnić. najbardziej „prywatna” funkcja to taka, która nie pojawia się w nagłówku.private:
metody nigdy nie mogą korzystać z tej korzyści.