W wielu kodach C ++ stosowane są konwencje składniowe do oznaczania zmiennych składowych. Typowe przykłady obejmują
- m_ memberName dla członków publicznych (w przypadku gdy w ogóle są wykorzystywani członkowie publiczni)
- _ nazwa_członka w przypadku członków prywatnych lub wszystkich członków
Inni próbują wymusić użycie this-> member za każdym razem, gdy używana jest zmienna składowa.
Z mojego doświadczenia wynika, że większość większych baz kodu zawodzi w konsekwentnym stosowaniu takich reguł.
W innych językach konwencje te są znacznie mniej rozpowszechnione. Widzę to tylko sporadycznie w kodzie Java lub C #. Myślę, że nigdy nie widziałem tego w kodzie Ruby lub Python. Dlatego wydaje się, że w bardziej nowoczesnych językach istnieje tendencja do nieużywania specjalnych znaczników dla zmiennych składowych.
Czy ta konwencja jest nadal przydatna dzisiaj w C ++, czy jest to tylko anachronizm. Zwłaszcza, że jest używany tak niespójnie w różnych bibliotekach. Czy inne języki nie wykazały, że można obejść się bez prefiksów członków?
źródło
self._something = 1
.this->member
w kodzie Pythona. W Pythonie jest to typoweself.member
i nie jest to tylko konwencja, wymaga tego język.Odpowiedzi:
Musisz uważać, używając wiodącego podkreślenia. Początkowy podkreślenie przed wielką literą w słowie jest zastrzeżone. Na przykład:
_Bla
_L
to wszystkie zarezerwowane słowa
_bla
_l
nie są. Istnieją inne sytuacje, w których początkowe podkreślenia przed małymi literami są niedozwolone. W moim konkretnym przypadku okazało się, że _L jest zarezerwowane przez Visual C ++ 2005 i zderzenie spowodowało nieoczekiwane rezultaty.
Nie wiem, jak przydatne jest oznaczanie zmiennych lokalnych.
Oto link o tym, które identyfikatory są zarezerwowane: Jakie są zasady dotyczące używania podkreślenia w identyfikatorze C ++?
źródło
Jestem zwolennikiem dobrze wykonanych przedrostków .
Myślę, że (systemowa) notacja węgierska jest odpowiedzialna za większość „złego rapu”, jaki dostają przedrostki.
Ta notacja jest w dużej mierze bezcelowa w językach silnie typowanych, np. W C ++ "lpsz", aby powiedzieć, że twój łańcuch jest długim wskaźnikiem do łańcucha zakończonego znakiem nul, kiedy: segmentowana architektura jest starożytną historią, łańcuchy C ++ są według zwykłej konwencji wskaźniki zakończone znakiem nul char tablice i nie jest aż tak trudno stwierdzić, że „customerName” to ciąg znaków!
Jednak używam prefiksów, aby określić użycie zmiennej (zasadniczo „Aplikacje węgierskie”, chociaż wolę unikać terminu węgierski, ponieważ ma on złe i niesprawiedliwe skojarzenia z systemem węgierskim), co jest bardzo przydatne i pozwala zaoszczędzić czas i podejście do redukcji błędów .
Używam:
Tam, gdzie chcę, aby typ był jasny, używam standardowych sufiksów (np. List, ComboBox itp.).
To sprawia, że programista jest świadomy użycia zmiennej za każdym razem, gdy ją widzi / używa. Prawdopodobnie najważniejszym przypadkiem jest "p" dla wskaźnika (ponieważ użycie zmienia się z var. Na var-> i musisz być dużo bardziej ostrożny ze wskaźnikami - NULL, arytmetyka wskaźników itp.), Ale wszystkie inne są bardzo przydatne.
Na przykład, możesz użyć tej samej nazwy zmiennej na wiele sposobów w jednej funkcji: (tutaj przykład w C ++, ale dotyczy to jednakowo wielu języków)
Możesz zobaczyć tutaj:
Kolejną wielką zaletą iteratorów „iName” jest to, że nigdy nie indeksuję tablicy z niewłaściwym indeksem, a jeśli skopiuję pętlę do innej pętli, nie muszę refaktoryzować jednej ze zmiennych indeksu pętli.
Porównaj ten nierealistycznie prosty przykład:
(co jest trudne do odczytania i często prowadzi do użycia „i” tam, gdzie „j” było zamierzone)
z:
(który jest znacznie bardziej czytelny i eliminuje wszelkie nieporozumienia związane z indeksowaniem. Dzięki funkcji autouzupełniania we współczesnych środowiskach IDE jest to również szybkie i łatwe do wpisania)
Następną korzyścią jest to, że fragmenty kodu nie wymagają żadnego kontekstu do zrozumienia. Mogę skopiować dwa wiersze kodu do wiadomości e-mail lub dokumentu, a każdy, kto czyta ten fragment, może odróżnić wszystkie elementy członkowskie, stałe, wskaźniki, indeksy itp. Nie muszę dodawać „och, i bądź ostrożny, ponieważ „dane” to wskaźnik do wskaźnika ”, ponieważ nazywa się„ ppData ”.
Z tego samego powodu nie muszę odrywać oczu od wiersza kodu, aby go zrozumieć. Nie muszę przeszukiwać kodu, aby dowiedzieć się, czy „dane” są lokalnymi parametrami, składowymi lub stałymi. Nie muszę przesuwać ręki do myszy, więc mogę najechać kursorem na „dane”, a następnie poczekać, aż pojawi się podpowiedź (która czasami nigdy się nie pojawia). Dzięki temu programiści mogą znacznie szybciej czytać i rozumieć kod , ponieważ nie tracą czasu na wyszukiwanie w górę iw dół lub czekanie.
Prefiks „m” pozwala również uniknąć brzydkiej i rozwlekłej notacji „to->” (IMHO) oraz niespójności, którą gwarantuje (nawet jeśli jesteś ostrożny, zwykle kończy się to mieszanką „this-> data” i „dane” w tej samej klasie, ponieważ nic nie wymusza spójnej pisowni nazwy).
„ten” zapis ma na celu rozwiązanie niejednoznaczności - ale dlaczego ktoś miałby celowo pisać kod, który może być niejednoznaczny? Niejednoznaczność będzie prowadzić do błędów prędzej czy później. W niektórych językach „this” nie może być używane dla statycznych elementów członkowskich, więc musisz wprowadzić „specjalne przypadki” w swoim stylu kodowania. Wolę mieć jedną, prostą regułę kodowania, która ma zastosowanie wszędzie - wyraźna, jednoznaczna i spójna.
Ostatnią ważną zaletą jest Intellisense i automatyczne uzupełnianie. Spróbuj użyć Intellisense w formularzu Windows, aby znaleźć zdarzenie - musisz przewinąć setki tajemniczych metod klasy bazowej, których nigdy nie będziesz musiał wywoływać, aby znaleźć zdarzenia. Gdyby jednak każde zdarzenie miało przedrostek „e”, byłoby automatycznie wymienione w grupie pod „e”. W ten sposób prefiksowanie działa w celu grupowania członków, stałych, wydarzeń itp. Na liście Intellisense, dzięki czemu znalezienie żądanych nazw jest znacznie szybsze i łatwiejsze. (Zwykle metoda może mieć około 20-50 wartości (lokalne, parametry, składowe, stałe, zdarzenia), które są dostępne w jej zakresie. Ale po wpisaniu prefiksu (chcę teraz użyć indeksu, wpisuję „i. .. ”), mam tylko 2–5 opcji autouzupełniania.„ Dodatkowe wpisywanie ”
Jestem leniwym programistą, a powyższa konwencja oszczędza mi dużo pracy. Potrafię kodować szybciej i popełniam znacznie mniej błędów, ponieważ wiem, jak należy wykorzystać każdą zmienną.
Argumenty przeciw
Więc jakie są wady? Typowe argumenty przeciwko prefiksom to:
„Schematy przedrostków są złe / złe” . Zgadzam się, że "m_lpsz" i im podobne są słabo przemyślane i całkowicie bezużyteczne. Dlatego radziłbym używać dobrze zaprojektowanej notacji zaprojektowanej tak, aby spełniała twoje wymagania, zamiast kopiować coś, co jest nieodpowiednie dla twojego kontekstu. (Użyj odpowiedniego narzędzia do pracy).
„Jeśli zmienię użycie czegoś, muszę zmienić nazwę” . Tak, oczywiście, że tak, o to właśnie chodzi w refaktoryzacji i dlaczego IDE mają narzędzia do refaktoryzacji, które wykonują tę pracę szybko i bezboleśnie. Nawet bez prefiksów zmiana użycia zmiennej prawie na pewno oznacza, że należy zmienić jej nazwę .
„Prefiksy mnie mylą” . Jak każde narzędzie, dopóki nie nauczysz się go używać. Gdy twój mózg przyzwyczai się do wzorców nazewnictwa, automatycznie odfiltruje informacje i nie będziesz mieć nic przeciwko temu, że prefiksy już tam są. Ale musisz solidnie używać takiego schematu przez tydzień lub dwa, zanim naprawdę staniesz się „płynny”. I wtedy wiele osób patrzy na stary kod i zaczyna się zastanawiać, jak sobie radzili bez dobrego schematu prefiksów.
„Mogę po prostu spojrzeć na kod, aby rozwiązać ten problem” . Tak, ale nie musisz tracić czasu na szukanie w innym miejscu kodu lub zapamiętywanie każdego najmniejszego szczegółu, gdy odpowiedź jest natychmiastowa, na której Twoje oko jest już skupione.
(Niektóre z tych informacji) można znaleźć, po prostu czekając na wyświetlenie podpowiedzi w mojej zmiennej . Tak. Tam, gdzie jest to obsługiwane, dla niektórych typów prefiksów, gdy kod kompiluje się bezproblemowo, po odczekaniu możesz przeczytać opis i znaleźć informacje, które prefiks by przekazał natychmiast. Czuję, że prefiks jest prostszym, bardziej niezawodnym i wydajniejszym podejściem.
„To więcej pisania” . Naprawdę? Jeszcze jeden znak? A może tak jest - dzięki narzędziom do automatycznego uzupełniania IDE często ogranicza to pisanie, ponieważ każdy znak prefiksu znacznie zawęża przestrzeń wyszukiwania. Naciśnij "e", a trzy wydarzenia w twojej klasie pojawią się w trybie Intellisense. Naciśnij "c", aby wyświetlić pięć stałych.
„Mogę użyć
this->
zamiastm
” . Cóż, tak, możesz. Ale to po prostu dużo brzydszy i bardziej rozwlekły przedrostek! Tyle, że niesie ze sobą dużo większe ryzyko (szczególnie w zespołach), ponieważ dla kompilatora jest opcjonalny , a zatem często jego użycie jest niespójne.m
z drugiej strony jest zwięzła, jasna, jednoznaczna i nie jest opcjonalna, więc przy jej użyciu o wiele trudniej jest popełnić błąd.źródło
z
jest to bardzo przydatne w języku takim jak C ++, w którym tego rodzaju szczegóły implementacji niskiego poziomu powinny być zawarte w klasie, ale w C (gdzie zerowe zakończenie jest ważną różnicą) Zgadzam się z tobą. IMO każdy schemat, którego używamy, powinien być dostosowany zgodnie z wymaganiami, aby najlepiej odpowiadał naszym własnym potrzebom - Więc jeśli zerowe zakończenie wpływa na użycie zmiennej, nie ma nic złego w zadeklarowaniu „z” użytecznego przedrostka.The most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers.
Z całego serca się nie zgadzam. Jeśli niewłaściwie użyję wskaźnika, po prostu się nie skompiluje (void*
może to być jednak wyjątek dla podwójnych wskaźników). I cały->
nad.
wystarczy mi powiedzieć, że jest to wskazówka. Ponadto, jeśli używasz autouzupełniania, twój edytor prawdopodobnie ma podpowiedzi deklaracji, eliminując potrzebę przedrostków dla informacji zmiennych. Niezależnie od tego, dobra odpowiedź.Generalnie nie używam przedrostka dla zmiennych składowych.
Kiedyś używałem
m
prefiksu, dopóki ktoś nie wskazał, że „C ++ ma już standardowy prefiks dostępu do członków:this->
.Więc tego teraz używam. Oznacza to, że w przypadku niejednoznaczności dodaję rozszerzenie
this->
przedrostek, ale zwykle nie ma dwuznaczności i mogę po prostu odwołać się bezpośrednio do nazwy zmiennej.Dla mnie to najlepsze z obu światów. Mam prefiks, którego mogę użyć, gdy go potrzebuję, i mogę go pominąć, gdy tylko jest to możliwe.
Oczywiście oczywistym przeciwieństwem tego jest „tak, ale wtedy nie można od razu zobaczyć, czy zmienna jest członkiem klasy, czy nie”.
Na co mówię „i co z tego? Jeśli chcesz to wiedzieć, Twoja klasa prawdopodobnie ma zbyt duży stan. Lub funkcja jest zbyt duża i skomplikowana”.
W praktyce stwierdziłem, że działa to wyjątkowo dobrze. Jako dodatkowy bonus pozwala mi łatwo promować zmienną lokalną dla członka klasy (lub odwrotnie), bez konieczności zmiany jej nazwy.
A co najważniejsze, jest spójny! Nie muszę robić nic specjalnego ani pamiętać o żadnych konwencjach, aby zachować spójność.
Nawiasem mówiąc, nie powinieneś używać wiodących podkreśleń dla członków swojej klasy. Nieprzyjemnie zbliżasz się do nazw zarezerwowanych przez implementację.
Standard zastrzega sobie wszystkie nazwy zaczynające się od podwójnego podkreślenia lub podkreślenia, po którym następuje duża litera. Zastrzega również wszystkie nazwy zaczynające się od pojedynczego podkreślenia w globalnej przestrzeni nazw .
Tak więc członek klasy z początkowym podkreśleniem, po którym następuje mała litera, jest legalny, ale wcześniej czy później zrobisz to samo z identyfikatorem zaczynającym się od dużej litery lub w inny sposób złamiesz jedną z powyższych zasad.
Dlatego łatwiej jest po prostu uniknąć wiodących podkreśleń. Użyj podkreślenia postfiksowego, lub po
m_
prostum
przedrostka, jeśli chcesz zakodować zakres w nazwie zmiennej.źródło
this->
jeśli chcesz określić, że jest to zmienna składowa, lub nie, to też jest dobre.this->
to znaczy.Wolę podkreślenia postfix, takie jak:
źródło
vector<int> v_;
i pisanie teżv_.push_back(5)
jest dość brzydkieOstatnio wolałem prefiks m_ zamiast w ogóle nie mieć przedrostka, powody nie są tak duże, że ważne jest oznaczanie zmiennych składowych, ale to, że unika się niejednoznaczności, powiedzmy, że masz kod taki jak:
void set_foo(int foo) { foo = foo; }
Przyczyna nie działa,
foo
dozwolona jest tylko jedna . Masz więc opcje:this->foo = foo;
Nie podoba mi się to, ponieważ powoduje cieniowanie parametrów, nie można już używać
g++ -Wshadow
ostrzeżeń, wtedy też dłużej można pisaćm_
. Nadal napotykasz konflikty nazewnictwa między zmiennymi i funkcjami, gdy masz aint foo;
i aint foo();
.foo = foo_;
lubfoo = arg_foo;
Używam tego od jakiegoś czasu, ale sprawia to, że listy argumentów są brzydkie, dokumentacja nie powinna zajmować się niejednoznacznością nazw w implementacji. Istnieją również konflikty nazewnictwa między zmiennymi i funkcjami.
m_foo = foo;
Dokumentacja API pozostaje czysta, nie ma niejednoznaczności między funkcjami składowymi i zmiennymi, a wtedy jest krótszy do wpisania
this->
. Jedyną wadą jest to, że sprawia, że struktury POD są brzydkie, ale ponieważ struktury POD nie cierpią z powodu niejednoznaczności nazwy, nie trzeba jej z nimi używać. Posiadanie unikalnego prefiksu ułatwia również kilka operacji wyszukiwania i zamiany.foo_ = foo;
Większość zalet
m_
zastosowania, ale odrzucam to ze względów estetycznych, końcowe lub wiodące podkreślenie sprawia, że zmienna wygląda na niekompletną i niezrównoważoną.m_
po prostu wygląda lepiej. Za pomocąm_
jest również bardziej rozszerzalne, ponieważ można go używaćg_
do globalnych is_
statycznych.PS: Powodem, dla którego nie widzisz tego
m_
w Pythonie lub Ruby, jest to, że oba języki wymuszają własny prefiks, Ruby używa@
dla zmiennych składowych, a Python wymagaself.
.źródło
foo
tylko dla członków, a zamiast tego użyj jednoliterowych lub krótkich nazw parametrów lub innych miejscowych / rzeczy odrzuconych, takich jakint f
; lub (b) poprzedzić coś parametrami lub innymi lokalnymi wartościami. dobra uwaga w kwestiim_
i strąków; Niezależnie doszedłem do wniosku, że w większości przypadków wolę przestrzegać obu tych wytycznych.Podczas czytania funkcji składowej wiedza o tym, kto jest „właścicielem” każdej zmiennej, jest absolutnie niezbędna do zrozumienia znaczenia zmiennej. W takiej funkcji:
... łatwo jest zobaczyć, skąd pochodzą jabłka i banany, ale co z winogronami, melonami i kiełkami? Czy powinniśmy szukać w globalnej przestrzeni nazw? W deklaracji klasy? Czy zmienna należy do tego obiektu, czy do klasy tego obiektu? Bez znajomości odpowiedzi na te pytania nie możesz zrozumieć kodu. W dłuższej funkcji nawet deklaracje zmiennych lokalnych, takich jak jabłka i banany, mogą się zgubić w tasowaniu.
Dołączenie spójnej etykiety dla zmiennych globalnych, zmiennych składowych i statycznych zmiennych składowych (być może odpowiednio g_, m_ i s_) natychmiast wyjaśnia sytuację.
Na początku może się do tego przyzwyczaić - ale co w programowaniu nie? Był dzień, kiedy nawet {i} wyglądali dla ciebie dziwnie. A kiedy już się do nich przyzwyczaisz, pomogą ci znacznie szybciej zrozumieć kod.
(Użycie „this->” zamiast m_ ma sens, ale jest jeszcze bardziej rozwlekłe i wizualnie destrukcyjne. Nie uważam tego za dobrą alternatywę do oznaczania wszystkich zastosowań zmiennych składowych).
Możliwym sprzeciwem wobec powyższego argumentu byłoby rozszerzenie argumentu na typy. Może być również prawdą, że znajomość typu zmiennej „jest absolutnie niezbędna do zrozumienia znaczenia zmiennej”. Jeśli tak jest, dlaczego nie dodać przedrostka do każdej nazwy zmiennej, która identyfikuje jej typ? Kierując się tą logiką, otrzymujesz notację węgierską. Ale wielu ludzi uważa, że notacja węgierska jest pracochłonna, brzydka i nieprzydatna.
język węgierski takpowiedz nam coś nowego o kodzie. Teraz rozumiemy, że w funkcji Foo :: bar () istnieje kilka niejawnych rzutów. Problem z kodem polega teraz na tym, że wartość informacji dodanych przez węgierskie prefiksy jest niewielka w stosunku do kosztu wizualnego. System typów C ++ zawiera wiele funkcji, które pomagają typom dobrze współpracować lub zgłaszać ostrzeżenie lub błąd kompilatora. Kompilator pomaga nam radzić sobie z typami - nie potrzebujemy do tego notacji. Możemy łatwo wywnioskować, że zmienne w Foo :: bar () są prawdopodobnie numeryczne, a jeśli to wszystko, co wiemy, to wystarczy, aby uzyskać ogólne zrozumienie funkcji. Dlatego wartość znajomości dokładnego typu każdej zmiennej jest stosunkowo niewielka. Jednak brzydota zmiennej takiej jak „s_dSpuds” (lub nawet po prostu „dSpuds”) jest świetna. Więc,
źródło
Nie mogę powiedzieć, jak bardzo jest to rozpowszechnione, ale osobiście zawsze (i zawsze) poprzedzałem zmienne składowe „m”. Na przykład:
To jedyna forma przedrostka, której używam (jestem bardzo anty węgierską notacją), ale przez lata zapewniała mi dobrą pozycję. Tak na marginesie, generalnie nie znoszę używania podkreśleń w nazwach (lub gdziekolwiek indziej), ale robię wyjątek dla nazw makr preprocesora, ponieważ zwykle wszystkie są pisane wielkimi literami.
źródło
a
w tym scenariuszu - inaczej nie robisz tego dobrze.mApData
(m
przedrostek, a następnie nazwa zmiennej toapData
).Głównym powodem przedrostka składowego jest rozróżnienie między lokalną funkcją składową a zmienną składową o tej samej nazwie. Jest to przydatne, jeśli używasz getterów z nazwą rzeczy.
Rozważać:
W tym przypadku nie można nazwać zmiennej składowej full_name. Musisz zmienić nazwę funkcji składowej na get_full_name () lub jakoś udekorować zmienną składową.
źródło
foo.name()
jest dużo bardziej czytelny niżfoo.get_name()
moim zdaniem.Nie sądzę, aby jedna składnia miała prawdziwą wartość nad inną. Wszystko sprowadza się, jak wspomniałeś, do jednolitości wszystkich plików źródłowych.
Jedynym punktem, w którym uważam takie zasady za interesujące, jest sytuacja, gdy potrzebuję 2 rzeczy o identycznych nazwach, na przykład:
Używam go do rozróżnienia tych dwóch. Również kiedy zawijam wywołania, jak z Windows Dll, RecvPacket (...) z Dll może być zawijane w RecvPacket (...) w moim kodzie. W takich szczególnych przypadkach użycie przedrostka takiego jak „_” może sprawić, że te dwa elementy będą podobne, łatwe do zidentyfikowania, który jest który, ale inny dla kompilatora
źródło
Niektóre odpowiedzi koncentrują się na refaktoryzacji, a nie konwencjach nazewnictwa, jako sposobie poprawy czytelności. Nie wydaje mi się, że jedno może zastąpić drugie.
Znam programistów, którzy nie lubią używać lokalnych deklaracji; wolą umieszczać wszystkie deklaracje na górze bloku (jak w C), aby wiedzieli, gdzie je znaleźć. Zauważyłem, że tam, gdzie pozwala na to określanie zakresu, deklarowanie zmiennych tam, gdzie są one używane po raz pierwszy, skraca czas, który spędzam na spoglądaniu wstecz, aby znaleźć deklaracje. (Dotyczy to nawet małych funkcji). Ułatwia mi to zrozumienie kodu, na który patrzę.
Mam nadzieję, że jest wystarczająco jasne, jak to się ma do konwencji nazewnictwa członków: Kiedy członkowie są jednolicie poprzedzeni, nigdy nie muszę w ogóle patrzeć wstecz; Wiem, że deklaracja nie zostanie nawet znaleziona w pliku źródłowym.
Jestem pewien, że nie zaczynałam preferować te style. Jednak z biegiem czasu, pracując w środowiskach, w których były one konsekwentnie używane, zoptymalizowałem swoje myślenie, aby je wykorzystać. Myślę, że jest możliwe, że wielu ludzi, którzy obecnie czują się z nimi niekomfortowo, również by je preferowali, biorąc pod uwagę konsekwentne stosowanie.
źródło
Te konwencje są po prostu tym. Większość sklepów stosuje konwencje kodu, aby ułatwić czytelność kodu, dzięki czemu każdy może łatwo spojrzeć na fragment kodu i szybko rozszyfrować między takimi elementami, jak członkowie publiczni i prywatni.
źródło
class
es, których wszyscy członkowie sąprivate
/protected
, albo PODstruct
s, których wszystkie zmienne sąpublic
(i często równieżconst
). Dlatego nigdy nie muszę się zastanawiać nad poziomem dostępu danego członka.Dzieje się tak zwykle dlatego, że nie ma przedrostka . Kompilator potrzebuje wystarczającej ilości informacji, aby rozwiązać daną zmienną, czy to unikatową nazwę ze względu na prefiks, czy za pośrednictwem
this
słowa kluczowego.Więc tak, myślę, że przedrostki są nadal przydatne. Ja na przykład wolałbym wpisać „_”, aby uzyskać dostęp do członka, zamiast „this->”.
źródło
struct Foo { int x; Foo(int x) : x(x) { ... } };
Foo(int x, bool blee) : x(x) { if (blee) x += bleecount; } // oops, forgot this->
Wolę nazywać moje zmienne składowe czymś użytecznym, a następnie podawać parametry konstruktora, które do nich pasują, skrócone nazwy:Foo(int f) : foo(f) {...}
Inne języki będą używać konwencji kodowania, po prostu są inne. Na przykład C # ma prawdopodobnie dwa różne style, których ludzie zwykle używają, albo jedną z metod C ++ (_variable, mVariable lub inny prefiks, taki jak notacja węgierska), lub to, co nazywam metodą StyleCop.
W końcu staje się tym, co ludzie wiedzą i co wygląda najlepiej. Osobiście uważam, że kod jest bardziej czytelny bez notacji węgierskiej, ale znalezienie zmiennej z inteligencją może być łatwiejsze, na przykład, jeśli dołączona jest notacja węgierska.
W powyższym przykładzie nie potrzebujesz prefiksu m dla zmiennych składowych, ponieważ poprzedzasz to użycie. wskazuje to samo w metodzie wymuszonej przez kompilator.
Niekoniecznie oznacza to, że inne metody są złe, ludzie trzymają się tego, co działa.
źródło
Kiedy masz dużą metodę lub bloki kodu, wygodnie jest od razu wiedzieć, czy używasz zmiennej lokalnej, czy elementu członkowskiego. ma to na celu uniknięcie błędów i lepszą przejrzystość!
źródło
-Wshadow
IMO, to sprawa osobista. W ogóle nie umieszczam żadnych przedrostków. W każdym razie, jeśli kod ma być publiczny, myślę, że powinien mieć kilka przedrostków, więc może być bardziej czytelny.
Często duże firmy używają własnych tak zwanych „reguł programistycznych”.
Przy okazji, najzabawniejszym, ale najmądrzejszym, jaki widziałem, był DRY KISS (Nie powtarzaj się. Keep It Simple, Stupid). :-)
źródło
Jak już powiedzieli inni, ważne jest, aby być potocznym (dostosowywać style nazewnictwa i konwencje do kodu, w którym piszesz) i być konsekwentnym.
Przez lata pracowałem na dużej bazie kodu, która używa zarówno konwencji „this->”, jak i notacji podkreślenia postfix dla zmiennych składowych. Przez lata pracowałem również nad mniejszymi projektami, z których niektóre nie miały żadnej konwencji nazewnictwa zmiennych składowych, a inne miały inne konwencje nazywania zmiennych składowych. Spośród tych mniejszych projektów konsekwentnie stwierdzałem, że te, które nie mają żadnej konwencji, są najtrudniejsze do szybkiego wskoczenia i zrozumienia.
Jestem bardzo skłonny do nazywania. Będę się męczyć nad nazwą, która ma być przypisana do klasy lub zmiennej do tego stopnia, że jeśli nie mogę wymyślić czegoś, co uważam za „dobre”, wybiorę nazwę jako coś bezsensownego i przedstawię komentarz opisujący, co to naprawdę jest jest. W ten sposób przynajmniej nazwa oznacza dokładnie to, co mam na myśli - nic dodać nic ująć. I często, po pewnym czasie używania go, odkrywam, jaka naprawdę powinna być nazwa, i mogę wrócić i odpowiednio zmodyfikować lub refaktoryzować.
Ostatnia uwaga na temat IDE wykonującego pracę - to wszystko fajne i dobre, ale IDE często nie są dostępne w środowiskach, w których wykonuję najpilniejszą pracę. Czasami jedyną dostępną rzeczą w tym momencie jest kopia „vi”. Ponadto widziałem wiele przypadków, w których uzupełnianie kodu IDE propagowało głupotę, taką jak niepoprawna pisownia w nazwach. Dlatego wolę nie polegać na kuli IDE.
źródło
Pierwotnym pomysłem na prefiksy w zmiennych składowych C ++ było przechowywanie dodatkowych informacji o typie, o których kompilator nie wiedział. Na przykład, możesz mieć łańcuch o stałej długości znaków, a drugi, który jest zmienny i zakończony znakiem „\ 0”. Dla kompilatora są to oba
char *
, ale jeśli spróbujesz skopiować z jednego do drugiego, wpadniesz w ogromne kłopoty. Więc z czubka mojej głowychar *aszFred = "Hi I'm a null-terminated string";
char *arrWilma = {'O', 'o', 'p', 's'};
gdzie „asz” oznacza, że ta zmienna jest „ciągiem ascii (zakończonym zerem), a„ arr ”oznacza, że ta zmienna jest tablicą znaków.
Wtedy dzieje się magia. Kompilator będzie doskonale zadowolony z tego stwierdzenia:
strcpy(arrWilma, aszFred);
Ale ty, jako człowiek, możesz spojrzeć na to i powiedzieć „hej, te zmienne nie są tak naprawdę tego samego typu, nie mogę tego zrobić”.
Niestety, wiele miejsc używa standardów, takich jak „m_” dla zmiennych składowych, „i” dla liczb całkowitych, niezależnie od tego, jak są używane, „cp” dla wskaźników znaków. Innymi słowy, powielają to, co wie kompilator, a jednocześnie utrudniają odczytanie kodu. Uważam, że ta zgubna praktyka powinna być prawnie zakazana i podlegać surowym karom.
Na koniec należy wspomnieć o dwóch kwestiach:
źródło
Nasz projekt zawsze używał „its” jako przedrostka dla danych składowych i „the” jako przedrostka dla parametrów, bez przedrostka dla lokalnych. To trochę fajne, ale zostało przyjęte przez pierwszych programistów naszego systemu, ponieważ widzieli, że jest on używany jako konwencja przez niektóre komercyjne biblioteki źródłowe, których używaliśmy w tamtym czasie (albo XVT, albo RogueWave - może obie). Otrzymasz coś takiego:
Głównym powodem, dla którego widzę zakres prefiksów (i żadnych innych - nienawidzę notacji węgierskiej), jest to, że zapobiega to wpadaniu w kłopoty, pisząc kod, w którym myślisz, że odnosisz się do jednej zmiennej, ale tak naprawdę odnosisz się do innej zmiennej o tej samej nazwie zdefiniowanej w zakresie lokalnym. Pozwala również uniknąć problemu wymyślania nazw zmiennych, które reprezentowałyby tę samą koncepcję, ale z różnymi zakresami, jak w powyższym przykładzie. W takim przypadku i tak musiałbyś wymyślić jakiś przedrostek lub inną nazwę dla parametru „theName” - czemu nie stworzyć spójnej reguły, która będzie obowiązywać wszędzie.
Samo użycie tego-> nie jest wystarczająco dobre - nie jesteśmy tak zainteresowani zmniejszaniem niejednoznaczności, jak zmniejszaniem błędów w kodowaniu, a maskowanie nazw za pomocą lokalnych identyfikatorów może być uciążliwe. To prawda, niektóre kompilatory mogą mieć opcję zgłaszania ostrzeżeń w przypadkach, w których zamaskowano nazwę w większym zakresie, ale te ostrzeżenia mogą stać się uciążliwe, jeśli pracujesz z dużym zestawem bibliotek innych firm, które akurat wybrały nazwy nieużywanych zmiennych, które czasami kolidują z Twoimi.
A co do samego siebie - szczerze mówiąc, łatwiej mi pisać niż podkreślenia (jako maszynistka dotykowa unikam podkreślenia, gdy tylko jest to możliwe - zbyt duże rozciąganie się od głównych rzędów) i uważam to za bardziej czytelne niż tajemniczy podkreślenie.
źródło
Używam go, ponieważ Intellisense w VC ++ nie może powiedzieć, kiedy pokazywać prywatnych członków podczas uzyskiwania dostępu poza klasą. Jedynym wskazaniem jest mały symbol „kłódki” na ikonie pola na liście Intellisense. Po prostu ułatwia identyfikację prywatnych członków (pól). Szczerze mówiąc, nawyk z C #.
źródło
Myślę, że jeśli potrzebujesz prefiksów, aby odróżnić członków klasy od parametrów funkcji składowych i zmiennych lokalnych, albo funkcja jest zbyt duża, albo zmienne są źle nazwane. Jeśli nie mieści się na ekranie, możesz łatwo zobaczyć, co jest czym, refaktoryzuj.
Biorąc pod uwagę, że często są deklarowane z dala od miejsca, w którym są używane, uważam, że konwencje nazewnictwa dla stałych globalnych (i zmiennych globalnych, chociaż IMO rzadko kiedy istnieje potrzeba ich użycia) mają sens. Ale poza tym nie widzę dużej potrzeby.
To powiedziawszy, zwykłem umieszczać podkreślenie na końcu wszystkich członków klasy prywatnej. Ponieważ wszystkie moje dane są prywatne, oznacza to, że członkowie mają na końcu podkreślenie. Zwykle już tego nie robię w nowych bazach kodu, ale ponieważ jako programista pracujesz głównie ze starym kodem, nadal często to robię. Nie jestem pewien, czy moja tolerancja dla tego nawyku wynika z tego, że robiłem to zawsze i nadal robię to regularnie, czy naprawdę ma to więcej sensu niż oznaczanie zmiennych składowych.
źródło
W Pythonie wiodące podwójne podkreślenia są używane do emulacji prywatnych członków. Aby uzyskać więcej informacji, zobacz tę odpowiedź
źródło
Ze względu na zarządzanie pamięcią przydatne jest rozróżnianie między zmiennymi składowymi i zmiennymi lokalnymi. Mówiąc ogólnie, zmienne składowe przydzielone do sterty powinny zostać zniszczone w destruktorze, podczas gdy zmienne lokalne przydzielone do sterty powinny zostać zniszczone w tym zakresie. Zastosowanie konwencji nazewnictwa do zmiennych składowych ułatwia prawidłowe zarządzanie pamięcią.
źródło
Code Complete zaleca m_varname jako zmienne składowe.
Chociaż nigdy nie sądziłem, że notacja m_ jest przydatna, przy tworzeniu standardu nadałbym opinii McConnellowi wagę.
źródło
Prawie nigdy nie używam przedrostków przed nazwami moich zmiennych. Jeśli używasz wystarczająco przyzwoitego IDE, powinieneś być w stanie łatwo refaktoryzować i znajdować odniesienia. Używam bardzo jasnych nazw i nie boję się mieć długich nazw zmiennych. Z tą filozofią też nigdy nie miałem problemów z zakresem.
Jedyny raz, kiedy używam prefiksu, byłby w wierszu podpisu. Przedrostuję parametry do metody znakiem _, aby móc programować wokół nich defensywnie.
źródło
Nigdy nie powinieneś potrzebować takiego przedrostka. Jeśli taki przedrostek oferuje jakąkolwiek korzyść, Twój styl kodowania ogólnie wymaga naprawy i to nie prefiks sprawia, że kod nie jest przejrzysty. Typowe złe nazwy zmiennych to „inne” lub „2”. Nie naprawiasz tego wymagając, aby była mOther, naprawiasz to, zmuszając programistę do przemyślenia tego, co robi ta zmienna w kontekście tej funkcji. Być może miał na myśli remoteSide, newValue, secondTestListener lub coś w tym zakresie.
To skuteczny anachronizm, który wciąż jest zbyt daleko rozpowszechniany. Przestań poprzedzać zmienne i nadaj im nazwy własne, których przejrzystość odzwierciedla czas ich używania. Maksymalnie 5 linii można nazwać „i” bez zamieszania; poza 50 liniami potrzebujesz dość długiej nazwy.
źródło
Lubię nazwy zmiennych, aby nadawać znaczenie tylko wartościom, które zawierają, i pozostawić sposób ich zadeklarowania / implementacji poza nazwą. Chcę wiedzieć, co oznacza wartość, kropka. Może zrobiłem więcej niż przeciętną ilość refaktoryzacji, ale uważam, że osadzenie sposobu, w jaki coś jest zaimplementowane w nazwie, sprawia, że refaktoryzacja jest bardziej żmudna, niż powinna. Prefiksy wskazujące, gdzie lub jak są deklarowane elementy składowe obiektu, są specyficzne dla implementacji.
Przez większość czasu nie obchodzi mnie, czy czerwony jest wyliczeniem, strukturą lub czymkolwiek, a jeśli funkcja jest tak duża, że nie pamiętam, czy kolor został zadeklarowany lokalnie, czy jest składnikiem, prawdopodobnie czas na przerwanie funkcję na mniejsze jednostki logiczne.
Jeśli twoja cykliczna złożoność jest tak duża, że nie możesz śledzić tego, co dzieje się w kodzie bez wskazówek specyficznych dla implementacji osadzonych w nazwach rzeczy, najprawdopodobniej musisz zmniejszyć złożoność swojej funkcji / metody.
Przeważnie używam „this” tylko w konstruktorach i inicjatorach.
źródło
Używam m_ do zmiennych składowych, aby skorzystać z Intellisense i powiązanych funkcji IDE. Kiedy koduję implementację klasy, mogę wpisać m_ i zobaczyć combobox ze wszystkimi członkami m_ zgrupowanymi razem.
Ale mógłbym żyć bez m_'s, oczywiście. To tylko mój styl pracy.
źródło
this->
Według JOINT STRIKE FIGHTER AIR VEHICLE C ++ STANDARDS (grudzień 2005):
W związku z tym przedrostek „m” staje się bezużyteczny, ponieważ wszystkie dane powinny być prywatne.
Ale dobrym zwyczajem jest używanie przedrostka p przed wskaźnikiem, ponieważ jest to niebezpieczna zmienna.
źródło
Wiele z tych konwencji pochodzi z czasów bez wyrafinowanych edytorów. Poleciłbym użycie odpowiedniego IDE, które pozwala na pokolorowanie każdego rodzaju zmiennej. Kolor jest zdecydowanie łatwiejszy do wykrycia niż jakikolwiek prefiks.
Jeśli potrzebujesz uzyskać jeszcze więcej szczegółów na temat zmiennej, każde nowoczesne IDE powinno być w stanie pokazać ci ją, przesuwając kursor lub kursor na nią. A jeśli użyjesz zmiennej w niewłaściwy sposób (na przykład wskaźnika z operatorem.), I tak otrzymasz błąd.
źródło