Viele C ++ - Codes verwenden syntaktische Konventionen zum Markieren von Mitgliedsvariablen. Häufige Beispiele sind
- m_ memberName für öffentliche Mitglieder (wo öffentliche Mitglieder überhaupt verwendet werden)
- _ memberName für private Mitglieder oder alle Mitglieder
Andere versuchen, die Verwendung von this-> member zu erzwingen, wenn eine Mitgliedsvariable verwendet wird.
Nach meiner Erfahrung können die meisten größeren Codebasen solche Regeln nicht konsistent anwenden.
In anderen Sprachen sind diese Konventionen weit weniger verbreitet. Ich sehe es nur gelegentlich in Java oder C # -Code. Ich glaube, ich habe es noch nie in Ruby- oder Python-Code gesehen. Daher scheint es bei moderneren Sprachen einen Trend zu geben, kein spezielles Markup für Mitgliedsvariablen zu verwenden.
Ist diese Konvention heute in C ++ noch nützlich oder ist sie nur ein Anachronismus? Zumal es in Bibliotheken so uneinheitlich verwendet wird. Haben die anderen Sprachen nicht gezeigt, dass man auf Mitgliederpräfixe verzichten kann?
quelle
self._something = 1
.this->member
in Python-Code gesehen. In Python ist dies normalerweise der Fallself.member
und es ist nicht nur eine Konvention, sondern wird von der Sprache benötigt.Antworten:
Sie müssen vorsichtig sein, wenn Sie einen führenden Unterstrich verwenden. Ein führender Unterstrich vor einem Großbuchstaben in einem Wort ist reserviert. Beispielsweise:
_Foo
_L
sind alle reservierten Wörter während
_foo
_l
sind nicht. Es gibt andere Situationen, in denen führende Unterstriche vor Kleinbuchstaben nicht zulässig sind. In meinem speziellen Fall stellte ich fest, dass _L zufällig von Visual C ++ 2005 reserviert wurde und der Konflikt einige unerwartete Ergebnisse verursachte.
Ich bin am Zaun darüber, wie nützlich es ist, lokale Variablen zu markieren.
Hier ist ein Link darüber, welche Bezeichner reserviert sind: Welche Regeln gelten für die Verwendung eines Unterstrichs in einem C ++ - Bezeichner?
quelle
Ich bin alle für gut gemachte Präfixe .
Ich denke, dass die ungarische (System-) Notation für den größten Teil des "schlechten Rufs" verantwortlich ist, den Präfixe erhalten.
Diese Notation ist in stark typisierten Sprachen, z. B. in C ++ "lpsz", weitgehend sinnlos, um Ihnen mitzuteilen, dass Ihre Zeichenfolge ein langer Zeiger auf eine nicht terminierte Zeichenfolge ist, wenn: Segmentierte Architektur eine alte Geschichte ist, C ++ - Zeichenfolgen nach gängigen Konventionen Zeiger auf nicht terminierte Zeichenfolgen sind char-Arrays, und es ist gar nicht so schwer zu wissen, dass "customerName" eine Zeichenfolge ist!
Ich verwende jedoch Präfixe, um die Verwendung einer Variablen anzugeben (im Wesentlichen "Apps Ungarisch", obwohl ich es vorziehe, den Begriff Ungarisch zu vermeiden, da er eine schlechte und unfaire Verbindung mit System Hungarian hat), und dies ist eine sehr praktische Zeitersparnis und Fehlerreduzierender Ansatz.
Ich benutze:
Wenn ich den Typ klarstellen möchte , verwende ich Standardsuffixe (z. B. List, ComboBox usw.).
Dies macht den Programmierer auf die Verwendung der Variablen aufmerksam, wenn er sie sieht / verwendet. Der wohl wichtigste Fall ist "p" für Zeiger (da sich die Verwendung von var. Zu var-> ändert und Sie mit Zeigern - NULL, Zeigerarithmetik usw. - viel vorsichtiger umgehen müssen), aber alle anderen sind sehr praktisch.
Beispielsweise können Sie denselben Variablennamen in einer einzigen Funktion auf verschiedene Arten verwenden: (hier ein C ++ - Beispiel, das jedoch für viele Sprachen gleichermaßen gilt)
Sie können hier sehen:
Ein weiterer großartiger Punkt bei "iName" -Iteratoren ist, dass ich niemals ein Array mit dem falschen Index indiziere. Wenn ich eine Schleife in eine andere Schleife kopiere, muss ich keine der Schleifenindexvariablen umgestalten.
Vergleichen Sie dieses unrealistisch einfache Beispiel:
(was schwer zu lesen ist und oft zur Verwendung von "i" führt, wo "j" beabsichtigt war)
mit:
(Dies ist viel besser lesbar und beseitigt alle Verwirrung über die Indizierung. Mit der automatischen Vervollständigung in modernen IDEs ist dies auch schnell und einfach einzugeben.)
Der nächste Vorteil ist, dass für Code-Snippets kein Kontext verstanden werden muss. Ich kann zwei Codezeilen in eine E-Mail oder ein Dokument kopieren, und jeder, der dieses Snippet liest, kann den Unterschied zwischen allen Elementen, Konstanten, Zeigern, Indizes usw. erkennen. Ich muss nicht "oh, und sei vorsichtig, weil" hinzufügen 'data' ist ein Zeiger auf einen Zeiger ", weil er 'ppData' heißt.
Und aus dem gleichen Grund muss ich meine Augen nicht aus einer Codezeile heraus bewegen, um sie zu verstehen. Ich muss den Code nicht durchsuchen, um festzustellen, ob 'data' ein Lokal, ein Parameter, ein Mitglied oder eine Konstante ist. Ich muss meine Hand nicht zur Maus bewegen, damit ich den Mauszeiger über 'Daten' bewegen und dann warten kann, bis ein Tooltip (der manchmal nie angezeigt wird) angezeigt wird. So können Programmierer den Code erheblich schneller lesen und verstehen , da sie keine Zeit damit verschwenden, nach oben und unten zu suchen oder zu warten.
Das Präfix 'm' vermeidet auch die (IMHO) hässliche und wortreiche "this->" - Notation und die damit verbundene Inkonsistenz (selbst wenn Sie vorsichtig sind, erhalten Sie normalerweise eine Mischung aus 'this-> data' und 'Daten' in derselben Klasse, da nichts eine konsistente Schreibweise des Namens erzwingt).
'diese' Notation soll Mehrdeutigkeiten auflösen - aber warum sollte jemand absichtlich Code schreiben, der mehrdeutig sein kann? Mehrdeutigkeit führt früher oder später zu einem Fehler. In einigen Sprachen kann "dies" nicht für statische Elemente verwendet werden. Daher müssen Sie "Sonderfälle" in Ihren Codierungsstil einfügen. Ich bevorzuge eine einzige einfache Codierungsregel, die überall gilt - explizit, eindeutig und konsistent.
Der letzte große Vorteil ist Intellisense und die automatische Vervollständigung. Versuchen Sie, Intellisense in einem Windows Form zu verwenden, um ein Ereignis zu finden. Sie müssen durch Hunderte mysteriöser Basisklassenmethoden scrollen, die Sie niemals aufrufen müssen, um die Ereignisse zu finden. Wenn jedoch jedes Ereignis ein "e" -Präfix hätte, würden sie automatisch in einer Gruppe unter "e" aufgeführt. Das Präfixieren dient daher dazu, die Mitglieder, Konstanten, Ereignisse usw. in der Intellisense-Liste zu gruppieren, wodurch es viel schneller und einfacher wird, die gewünschten Namen zu finden. (Normalerweise kann eine Methode etwa 20-50 Werte (Lokale, Parameter, Mitglieder, Konstanten, Ereignisse) haben, auf die in ihrem Bereich zugegriffen werden kann. Nach der Eingabe des Präfixes (ich möchte jetzt einen Index verwenden, gebe ich also 'i' ein. .. '), mir werden nur 2-5 Optionen für die automatische Vervollständigung angezeigt. Die' zusätzliche Eingabe '
Ich bin ein fauler Programmierer, und die obige Konvention erspart mir viel Arbeit. Ich kann schneller codieren und mache weit weniger Fehler, weil ich weiß, wie jede Variable verwendet werden soll.
Argumente gegen
Also, was sind die Nachteile? Typische Argumente gegen Präfixe sind:
"Präfixschemata sind schlecht / böse" . Ich bin damit einverstanden, dass "m_lpsz" und seine Art schlecht durchdacht und völlig nutzlos sind. Aus diesem Grund würde ich empfehlen, eine gut gestaltete Notation zu verwenden, die Ihre Anforderungen unterstützt, anstatt etwas zu kopieren, das für Ihren Kontext ungeeignet ist. (Verwenden Sie das richtige Werkzeug für den Job).
"Wenn ich die Verwendung von etwas ändere, muss ich es umbenennen" . Ja, natürlich tun Sie das. Darum geht es beim Refactoring und darum, warum IDEs über Refactoring-Tools verfügen, um diese Aufgabe schnell und schmerzlos zu erledigen. Auch ohne Präfixe, die Verwendung eines variablen Veränderung bedeutet fast sicher sein Name sollte geändert werden.
"Präfixe verwirren mich nur" . Wie jedes Werkzeug, bis Sie lernen, wie man es benutzt. Sobald sich Ihr Gehirn an die Namensmuster gewöhnt hat, filtert es die Informationen automatisch heraus und es macht Ihnen nichts aus, dass die Präfixe nicht mehr vorhanden sind. Aber Sie müssen ein oder zwei Wochen lang ein solches Schema anwenden, bevor Sie wirklich "fließend" werden. Und dann schauen sich viele Leute alten Code an und fragen sich, wie sie es jemals ohne ein gutes Präfixschema geschafft haben.
"Ich kann mir nur den Code ansehen, um dieses Zeug herauszuarbeiten" . Ja, aber Sie müssen keine Zeit damit verschwenden, an anderer Stelle im Code nachzuschauen oder sich an jedes Detail zu erinnern, wenn die Antwort genau an der Stelle ist, auf die Ihr Auge bereits fokussiert ist.
(Einige) dieser Informationen können gefunden werden, indem Sie nur darauf warten, dass ein Tooltip in meiner Variablen angezeigt wird . Ja. Wenn dies unterstützt wird, können Sie bei einigen Präfixtypen, wenn Ihr Code sauber kompiliert wurde, nach einer Wartezeit eine Beschreibung durchlesen und die Informationen finden, die das Präfix sofort übermittelt hätte. Ich bin der Meinung, dass das Präfix ein einfacherer, zuverlässigerer und effizienterer Ansatz ist.
"Es ist mehr tippen" . "Ja wirklich?" Ein ganzer Charakter mehr? Oder ist es das? Mit IDE-Tools zur automatischen Vervollständigung wird die Eingabe häufig reduziert, da jedes Präfixzeichen den Suchraum erheblich einschränkt. Drücken Sie "e" und die drei Ereignisse in Ihrer Klasse werden in Intellisense angezeigt. Drücken Sie "c" und die fünf Konstanten werden aufgelistet.
"Ich kann
this->
anstelle von verwendenm
" . Ja, das kannst du. Aber das ist nur ein viel hässlicheres und ausführlicheres Präfix! Nur es birgt ein weitaus größeres Risiko (insbesondere in Teams), da es für den Compiler optional ist und daher seine Verwendung häufig inkonsistent ist.m
Auf der anderen Seite ist es kurz, klar, explizit und nicht optional, so dass es viel schwieriger ist, Fehler damit zu machen.quelle
z
dies in einer Sprache wie C ++ sehr oft nützlich ist, in der diese Art von Implementierungsdetails auf niedriger Ebene in einer Klasse gekapselt werden sollten, aber in C (wo Nullterminierung eine wichtige Unterscheidung ist) stimme ich Ihnen zu. IMO sollte jedes von uns verwendete Schema nach Bedarf an unsere eigenen Bedürfnisse angepasst werden. Wenn sich die Nullterminierung auf Ihre Verwendung der Variablen auswirkt, ist es nichts Falsches, "z" als nützliches Präfix zu deklarieren.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.
Ich bin von ganzem Herzen anderer Meinung. Wenn ich einen falschen Zeiger verwende, wird er einfach nicht kompiliert (void*
kann jedoch eine Ausnahme für Doppelzeiger sein). Und das ganze->
über.
genug ist , um mir zu sagen , es ist ein Zeiger. Wenn Sie die automatische Vervollständigung verwenden, verfügt Ihr Editor wahrscheinlich über Deklarationstooltips, sodass keine Präfixe für Variableninformationen erforderlich sind. Egal, gute Antwort.Ich verwende im Allgemeinen kein Präfix für Mitgliedsvariablen.
Ich habe früher ein
m
Präfix verwendet, bis jemand darauf hinwies, dass "C ++ bereits ein Standardpräfix für den Mitgliederzugriff hat :this->
.Das ist es, was ich jetzt benutze. Das heißt, wenn es Mehrdeutigkeiten gibt , füge ich das
this->
Präfix hinzu, aber normalerweise besteht keine Mehrdeutigkeit, und ich kann einfach direkt auf den Variablennamen verweisen.Für mich ist das das Beste aus beiden Welten. Ich habe ein Präfix, das ich verwenden kann, wenn ich es brauche, und ich kann es nach Möglichkeit weglassen.
Der offensichtliche Gegenpol dazu ist natürlich "Ja, aber dann können Sie nicht auf einen Blick sehen, ob eine Variable ein Klassenmitglied ist oder nicht".
Zu dem sage ich "na und? Wenn Sie das wissen müssen, hat Ihre Klasse wahrscheinlich zu viel Status. Oder die Funktion ist zu groß und kompliziert".
In der Praxis habe ich festgestellt, dass dies sehr gut funktioniert. Als zusätzlichen Bonus kann ich eine lokale Variable einfach einem Klassenmitglied (oder umgekehrt) empfehlen, ohne sie umbenennen zu müssen.
Und das Beste ist, es ist konsequent! Ich muss nichts Besonderes tun oder mich an Konventionen erinnern, um die Konsistenz aufrechtzuerhalten.
Übrigens sollten Sie für Ihre Klassenmitglieder keine führenden Unterstriche verwenden. Sie kommen unangenehm nahe an Namen heran, die von der Implementierung reserviert werden.
Der Standard reserviert alle Namen, beginnend mit doppeltem Unterstrich oder Unterstrich, gefolgt von Großbuchstaben. Außerdem werden alle Namen reserviert, die mit einem einzelnen Unterstrich im globalen Namespace beginnen .
Ein Klassenmitglied mit einem führenden Unterstrich gefolgt von einem Kleinbuchstaben ist also legal, aber früher oder spät werden Sie dasselbe mit einem Bezeichner tun, der mit Großbuchstaben beginnt, oder auf andere Weise gegen eine der oben genannten Regeln verstoßen.
Es ist also einfacher, führende Unterstriche zu vermeiden. Verwenden Sie einen Postfix-Unterstrich oder ein
m_
oder nur einm
Präfix, wenn Sie den Bereich im Variablennamen codieren möchten.quelle
this->
Sie sie nur, wenn Sie angeben müssen, dass es sich um eine Mitgliedsvariable handelt, oder nicht, das ist auch gut.this->
bedeutet.Ich bevorzuge Postfix-Unterstriche wie diesen:
quelle
vector<int> v_;
und das Schreibenv_.push_back(5)
ist auch ziemlich hässlichIn letzter Zeit habe ich eher das Präfix m_ bevorzugt, als überhaupt kein Präfix zu haben. Die Gründe sind nicht so sehr, dass es wichtig ist, Mitgliedsvariablen zu kennzeichnen, sondern dass es Mehrdeutigkeiten vermeidet, sagen wir, Sie haben Code wie:
void set_foo(int foo) { foo = foo; }
Das aus gutem Grund funktioniert nicht, nur einer ist
foo
erlaubt. Sie haben also folgende Möglichkeiten:this->foo = foo;
Ich mag es nicht, da es Parameter-Shadowing verursacht, können Sie keine
g++ -Wshadow
Warnungen mehr verwenden , es ist dann auch länger zu tippenm_
. Sie stoßen auch immer noch auf Namenskonflikte zwischen Variablen und Funktionen, wenn Sie aint foo;
und a habenint foo();
.foo = foo_;
oderfoo = arg_foo;
Ich benutze das schon eine Weile, aber es macht die Argumentlisten hässlich. Die Dokumentation sollte sich nicht mit der Eindeutigkeit von Namen in der Implementierung befassen. Auch hier bestehen Namenskonflikte zwischen Variablen und Funktionen.
m_foo = foo;
Die API-Dokumentation bleibt sauber, Sie erhalten keine Mehrdeutigkeit zwischen Elementfunktionen und Variablen und die Eingabe ist dann kürzer
this->
. Der einzige Nachteil ist, dass es POD-Strukturen hässlich macht, aber da POD-Strukturen überhaupt nicht unter der Namensmehrdeutigkeit leiden, muss man sie nicht mit ihnen verwenden. Ein eindeutiges Präfix erleichtert auch einige Such- und Ersetzungsvorgänge.foo_ = foo;
Die meisten Vorteile
m_
gelten, aber ich lehne es aus ästhetischen Gründen ab. Ein nachfolgender oder führender Unterstrich lässt die Variable nur unvollständig und unausgeglichen aussehen.m_
sieht einfach besser aus. Die Verwendungm_
ist auch erweiterbarer, da Sie sieg_
für globale unds_
statische Elemente verwenden können .PS: Der Grund, warum Sie
m_
in Python oder Ruby nicht sehen, ist, dass beide Sprachen ihr eigenes Präfix erzwingen, das Ruby@
für Mitgliedsvariablen verwendet und Python benötigtself.
.quelle
foo
nur für Mitglieder und verwenden Sie stattdessen Einzelbuchstaben oder Kurznamen für Parameter oder andere Einheimische / Auswege, wie zint f
. oder (b) den Parametern oder anderen Einheimischen etwas voranstellen . guter Punkt bezüglichm_
und Hülsen; Ich bin unabhängig voneinander zu der Präferenz gekommen, diese beiden Richtlinien größtenteils zu befolgen.Beim Lesen einer Mitgliedsfunktion ist es unbedingt erforderlich zu wissen, wem jede Variable "gehört", um die Bedeutung der Variablen zu verstehen. In einer Funktion wie dieser:
... es ist leicht zu erkennen, woher Äpfel und Bananen kommen, aber was ist mit Trauben, Melonen und Spuds? Sollen wir im globalen Namespace suchen? In der Klassenerklärung? Ist die Variable ein Mitglied dieses Objekts oder ein Mitglied der Klasse dieses Objekts? Ohne die Antwort auf diese Fragen zu kennen, können Sie den Code nicht verstehen. Und in einer längeren Funktion können sogar die Deklarationen lokaler Variablen wie Äpfel und Bananen im Shuffle verloren gehen.
Das Voranstellen einer konsistenten Bezeichnung für Globale, Elementvariablen und statische Elementvariablen (möglicherweise g_, m_ bzw. s_) verdeutlicht sofort die Situation.
Diese mögen zunächst etwas gewöhnungsbedürftig sein - aber was macht die Programmierung dann nicht? Es gab einen Tag, an dem sogar {und} für dich komisch aussahen. Und sobald Sie sich an sie gewöhnt haben, helfen sie Ihnen, den Code viel schneller zu verstehen.
(Die Verwendung von "this->" anstelle von m_ ist sinnvoll, aber noch langwieriger und visuell störender. Ich sehe es nicht als gute Alternative, um alle Verwendungen von Mitgliedsvariablen zu markieren.)
Ein möglicher Einwand gegen das obige Argument wäre, das Argument auf Typen auszudehnen. Es könnte auch zutreffen, dass die Kenntnis des Typs einer Variablen "für das Verständnis der Bedeutung der Variablen unbedingt erforderlich ist". Wenn dem so ist, warum nicht jedem Variablennamen ein Präfix hinzufügen, das seinen Typ identifiziert? Mit dieser Logik erhalten Sie die ungarische Notation. Aber viele Menschen finden die ungarische Notation mühsam, hässlich und nicht hilfreich.
ungarisch tutErzählen Sie uns etwas Neues über den Code. Wir verstehen jetzt, dass die Funktion Foo :: bar () mehrere implizite Casts enthält. Das Problem mit dem Code besteht nun darin, dass der Wert der durch ungarische Präfixe hinzugefügten Informationen im Verhältnis zu den visuellen Kosten gering ist. Das C ++ - Typsystem enthält viele Funktionen, mit denen Typen entweder gut zusammenarbeiten oder eine Compiler-Warnung oder einen Compiler-Fehler auslösen können. Der Compiler hilft uns beim Umgang mit Typen - wir brauchen dazu keine Notation. Wir können leicht genug schließen, dass die Variablen in Foo :: bar () wahrscheinlich numerisch sind, und wenn das alles ist, was wir wissen, ist das gut genug, um ein allgemeines Verständnis der Funktion zu erlangen. Daher ist der Wert, den genauen Typ jeder Variablen zu kennen, relativ gering. Die Hässlichkeit einer Variablen wie "s_dSpuds" (oder auch nur "dSpuds") ist jedoch großartig. So,
quelle
Ich kann nicht sagen, wie weit verbreitet es ist, aber persönlich habe ich meinen Mitgliedsvariablen immer (und immer) 'm' vorangestellt. Z.B:
Es ist die einzige Form des Präfixes, die ich verwende (ich bin sehr anti-ungarisch), aber es hat mir im Laufe der Jahre gute Dienste geleistet. Abgesehen davon verabscheue ich im Allgemeinen die Verwendung von Unterstrichen in Namen (oder irgendwo anders), mache aber eine Ausnahme für Präprozessor-Makronamen, da diese normalerweise alle in Großbuchstaben geschrieben sind.
quelle
a
in diesem Szenario groß schreiben - Sie machen es sonst nicht richtig.mApData
(m
Präfix, dann ist der VariablennameapData
).Der Hauptgrund für ein Elementpräfix besteht darin, zwischen einer lokalen Elementfunktion und einer gleichnamigen Elementvariablen zu unterscheiden. Dies ist nützlich, wenn Sie Getter mit dem Namen der Sache verwenden.
Erwägen:
Die Mitgliedsvariable konnte in diesem Fall nicht als vollständiger Name bezeichnet werden. Sie müssen die Elementfunktion in get_full_name () umbenennen oder die Elementvariable irgendwie dekorieren.
quelle
foo.name()
ist viel besser lesbar alsfoo.get_name()
meiner Meinung nach.Ich glaube nicht, dass eine Syntax einen echten Wert gegenüber einer anderen hat. Wie Sie bereits erwähnt haben, läuft alles auf die Einheitlichkeit der Quelldateien hinaus.
Der einzige Punkt, an dem ich solche Regeln interessant finde, ist, wenn ich zwei Dinge brauche, die als identisch bezeichnet werden, zum Beispiel:
Ich benutze es, um die beiden zu unterscheiden. Auch wenn ich Aufrufe wie aus der Windows-DLL einschließe, wird RecvPacket (...) aus der DLL möglicherweise in RecvPacket (...) in meinem Code eingeschlossen. In diesen besonderen Fällen kann die Verwendung eines Präfixes wie "_" dazu führen, dass die beiden gleich aussehen. Sie können leicht erkennen, welches welches ist, unterscheiden sich jedoch für den Compiler
quelle
Einige Antworten konzentrieren sich eher auf das Refactoring als auf Namenskonventionen, um die Lesbarkeit zu verbessern. Ich habe nicht das Gefühl, dass einer den anderen ersetzen kann.
Ich kenne Programmierer, denen es unangenehm ist, lokale Deklarationen zu verwenden. Sie ziehen es vor, alle Deklarationen oben in einem Block zu platzieren (wie in C), damit sie wissen, wo sie zu finden sind. Ich habe festgestellt, dass das Deklarieren von Variablen dort, wo sie zuerst verwendet werden, die Zeit verringert, die ich damit verbringe, nach hinten zu schauen, um die Deklarationen zu finden, wenn das Scoping dies zulässt. (Dies gilt für mich auch für kleine Funktionen.) Dadurch kann ich den Code, den ich betrachte, leichter verstehen.
Ich hoffe, es ist klar genug, wie dies mit den Namenskonventionen für Mitglieder zusammenhängt: Wenn Mitgliedern ein einheitliches Präfix vorangestellt wird, muss ich nie zurückblicken. Ich weiß, dass die Deklaration nicht einmal in der Quelldatei gefunden wird.
Ich bin mir sicher, dass ich diese Stile nicht bevorzugt habe. Im Laufe der Zeit habe ich in Umgebungen gearbeitet, in denen sie konsequent eingesetzt wurden, und mein Denken optimiert, um sie zu nutzen. Ich denke, es ist möglich, dass viele Leute, die sich derzeit mit ihnen unwohl fühlen, sie auch bevorzugen, wenn sie konsequent verwendet werden.
quelle
Diese Konventionen sind genau das. Die meisten Geschäfte verwenden Code-Konventionen, um die Lesbarkeit des Codes zu verbessern, sodass jeder leicht einen Code betrachten und schnell zwischen öffentlichen und privaten Mitgliedern unterscheiden kann.
quelle
class
alle Mitglieder, dieprivate
/ sindprotected
, oder PODs,struct
deren Variablen alle sindpublic
(und oft auchconst
). Ich muss mich also nie über die Zugriffsebene eines bestimmten Mitglieds wundern.Das liegt normalerweise daran, dass es kein Präfix gibt . Der Compiler benötigt genügend Informationen, um die betreffende Variable aufzulösen, sei es ein eindeutiger Name aufgrund des Präfixes oder über das
this
Schlüsselwort.Also, ja, ich denke Präfixe sind immer noch nützlich. Zum einen würde ich lieber '_' eingeben, um auf ein Mitglied zuzugreifen, als 'this->'.
quelle
struct Foo { int x; Foo(int x) : x(x) { ... } };
Foo(int x, bool blee) : x(x) { if (blee) x += bleecount; } // oops, forgot this->
vorziehen, meine Mitgliedsvariablen als nützlich zu bezeichnen und dann Konstruktorparameter anzugeben, die mit den abgekürzten Namen übereinstimmen:Foo(int f) : foo(f) {...}
Andere Sprachen verwenden Codierungskonventionen, sie sind lediglich unterschiedlich. C # zum Beispiel hat wahrscheinlich zwei verschiedene Stile, die normalerweise verwendet werden, entweder eine der C ++ - Methoden (_variable, mVariable oder ein anderes Präfix wie die ungarische Notation) oder das, was ich als StyleCop-Methode bezeichne.
Am Ende wird es das, was die Leute wissen und was am besten aussieht. Ich persönlich denke, dass Code ohne ungarische Notation besser lesbar ist, aber es kann einfacher werden, eine Variable mit Intellisense zu finden, wenn beispielsweise die ungarische Notation angehängt ist.
In meinem obigen Beispiel benötigen Sie kein m-Präfix für Mitgliedsvariablen, da Sie Ihrer Verwendung dieses Präfix voranstellen. zeigt dasselbe in einer vom Compiler erzwungenen Methode an.
Dies bedeutet nicht unbedingt, dass die anderen Methoden schlecht sind. Die Leute halten sich an das, was funktioniert.
quelle
Wenn Sie eine große Methode oder Codeblöcke haben, ist es praktisch, sofort zu wissen, ob Sie eine lokale Variable oder ein Mitglied verwenden. Es geht darum, Fehler zu vermeiden und die Übersichtlichkeit zu verbessern!
quelle
-Wshadow
IMO, das ist persönlich. Ich setze überhaupt keine Präfixe. Wenn Code öffentlich sein soll, sollte er meiner Meinung nach besser einige Präfixe haben, damit er besser lesbar ist.
Oft verwenden große Unternehmen ihre eigenen sogenannten "Entwicklerregeln".
Übrigens war der lustigste und klügste, den ich gesehen habe, DRY KISS (Wiederholen Sie sich nicht. Halten Sie es einfach, dumm). :-)
quelle
Wie andere bereits gesagt haben, ist es wichtig, umgangssprachlich zu sein (Namensstile und Konventionen an die Codebasis anzupassen, in der Sie schreiben) und konsistent zu sein.
Ich habe jahrelang an einer großen Codebasis gearbeitet, die sowohl die "this->" -Konvention als auch ein Postfix verwendet Unterstrichnotation für Mitgliedsvariablen verwendet. Im Laufe der Jahre habe ich auch an kleineren Projekten gearbeitet, von denen einige keine Konvention zum Benennen von Mitgliedsvariablen hatten und andere unterschiedliche Konventionen zum Benennen von Mitgliedsvariablen hatten. Von diesen kleineren Projekten habe ich immer wieder festgestellt, dass diejenigen, denen eine Konvention fehlte, am schwierigsten sind, schnell darauf zuzugreifen und sie zu verstehen.
Ich bin sehr anal-zurückhaltend in Bezug auf die Benennung. Ich werde mich über den Namen quälen, der einer Klasse oder Variablen zugeordnet werden soll, bis zu dem Punkt, dass ich, wenn ich nichts finden kann, was ich für "gut" halte, ihn als unsinnig bezeichnen und einen Kommentar abgeben werde, der beschreibt, was er wirklich ist ist. Auf diese Weise bedeutet zumindest der Name genau das, was ich beabsichtige - nicht mehr und nicht weniger. Und oft, nachdem ich es für eine Weile benutzt habe, entdecke ich, wie der Name wirklich sein sollte und kann zurückgehen und ihn entsprechend modifizieren oder umgestalten.
Ein letzter Punkt zum Thema einer IDE, die die Arbeit erledigt - das ist alles schön und gut, aber IDEs sind oft nicht in Umgebungen verfügbar, in denen ich die dringendste Arbeit ausgeführt habe. Manchmal ist zu diesem Zeitpunkt nur eine Kopie von 'vi' verfügbar. Außerdem habe ich viele Fälle gesehen, in denen die Vervollständigung des IDE-Codes Dummheit verbreitet hat, wie z. B. falsche Schreibweise in Namen. Daher möchte ich mich lieber nicht auf eine IDE-Krücke verlassen.
quelle
Die ursprüngliche Idee für Präfixe in C ++ - Mitgliedsvariablen bestand darin, zusätzliche Typinformationen zu speichern, von denen der Compiler nichts wusste. So könnten Sie beispielsweise eine Zeichenfolge haben, die eine feste Länge von Zeichen hat, und eine andere, die variabel ist und mit einem '\ 0' abgeschlossen wird. Für den Compiler sind sie beide
char *
, aber wenn Sie versuchen, von einem zum anderen zu kopieren, bekommen Sie große Probleme. Also, aus dem Kopf,char *aszFred = "Hi I'm a null-terminated string";
char *arrWilma = {'O', 'o', 'p', 's'};
Dabei bedeutet "asz", dass diese Variable "ascii string (nullterminiert) ist, und" arr "bedeutet, dass diese Variable ein Zeichenarray ist.
Dann passiert die Magie. Der Compiler wird mit dieser Aussage vollkommen zufrieden sein:
strcpy(arrWilma, aszFred);
Aber Sie als Mensch können es sich ansehen und sagen: "Hey, diese Variablen sind nicht wirklich vom selben Typ, das kann ich nicht."
Leider verwenden viele Orte Standards wie "m_" für Mitgliedsvariablen, "i" für Ganzzahlen, egal wie verwendet, "cp" für Zeichenzeiger. Mit anderen Worten, sie duplizieren das, was der Compiler weiß, und machen den Code gleichzeitig schwer lesbar. Ich glaube, diese schädliche Praxis sollte gesetzlich verboten und mit harten Strafen belegt werden.
Schließlich gibt es zwei Punkte, die ich erwähnen sollte:
quelle
Unser Projekt hat immer "its" als Präfix für Mitgliedsdaten und "the" als Präfix für Parameter verwendet, ohne Präfix für Einheimische. Es ist ein wenig niedlich, aber es wurde von den frühen Entwicklern unseres Systems übernommen, weil sie es als Konvention von einigen kommerziellen Quellbibliotheken sahen, die wir zu dieser Zeit verwendeten (entweder XVT oder RogueWave - vielleicht beide). Sie würden also so etwas bekommen:
Der Hauptgrund, den ich für das Scoping von Präfixen sehe (und keine anderen - ich hasse die ungarische Notation), ist, dass Sie dadurch nicht in Schwierigkeiten geraten, indem Sie Code schreiben, in dem Sie glauben, auf eine Variable zu verweisen, aber wirklich auf eine andere Variable mit demselben Namen, der im lokalen Bereich definiert ist. Es wird auch das Problem vermieden, Variablennamen zu erstellen, die dasselbe Konzept darstellen, jedoch unterschiedliche Bereiche haben, wie im obigen Beispiel. In diesem Fall müssten Sie sich ohnehin ein Präfix oder einen anderen Namen für den Parameter "theName" einfallen lassen - warum nicht eine konsistente Regel erstellen, die überall gilt?
Nur dies zu verwenden-> ist nicht wirklich gut genug - wir sind nicht so sehr daran interessiert, Mehrdeutigkeiten zu reduzieren wie an Codierungsfehlern, und das Maskieren von Namen mit Bezeichnern mit lokalem Gültigkeitsbereich kann schmerzhaft sein. Zugegeben, einige Compiler haben möglicherweise die Möglichkeit, Warnungen für Fälle auszulösen, in denen Sie den Namen in einem größeren Bereich maskiert haben. Diese Warnungen können jedoch zu einem Ärgernis werden, wenn Sie mit einer großen Anzahl von Bibliotheken von Drittanbietern arbeiten, die zufällig ausgewählt wurden Namen für nicht verwendete Variablen, die gelegentlich mit Ihren eigenen kollidieren.
Was das Selbst angeht - ich finde es ehrlich gesagt einfacher zu tippen als Unterstriche (als Touch-Typist vermeide ich Unterstriche, wann immer dies möglich ist - zu viel Ausdehnung der Ausgangsreihen), und ich finde es lesbarer als einen mysteriösen Unterstrich.
quelle
Ich benutze es, weil Intellisense von VC ++ nicht sagen kann, wann private Mitglieder beim Zugriff außerhalb der Klasse angezeigt werden sollen. Die einzige Anzeige ist ein kleines "Schlosssymbol" auf dem Feldsymbol in der Intellisense-Liste. Es macht es einfach einfacher, private Mitglieder (Felder) zu identifizieren. Auch eine Gewohnheit von C #, um ehrlich zu sein.
quelle
Ich denke, wenn Sie Präfixe benötigen, um Klassenmitglieder von Elementfunktionsparametern und lokalen Variablen zu unterscheiden, ist entweder die Funktion zu groß oder die Variablen sind schlecht benannt. Wenn es nicht auf den Bildschirm passt, sodass Sie leicht sehen können, was was ist, refactor.
Angesichts der Tatsache, dass sie häufig weit entfernt von ihrem Verwendungsort deklariert werden, finde ich, dass Namenskonventionen für globale Konstanten (und globale Variablen, obwohl IMO diese selten verwenden muss) sinnvoll sind. Aber sonst sehe ich nicht viel Bedarf.
Trotzdem habe ich am Ende aller privaten Klassenmitglieder einen Unterstrich gesetzt. Da alle meine Daten privat sind, bedeutet dies, dass Mitglieder einen nachgestellten Unterstrich haben. Normalerweise mache ich das nicht mehr in neuen Codebasen, aber da Sie als Programmierer meistens mit altem Code arbeiten, mache ich das immer noch viel. Ich bin mir nicht sicher, ob meine Toleranz für diese Gewohnheit darauf zurückzuführen ist, dass ich dies immer getan habe und es immer noch regelmäßig mache oder ob es wirklich sinnvoller ist als das Markieren von Mitgliedsvariablen.
quelle
In Python werden führende doppelte Unterstriche verwendet, um private Mitglieder zu emulieren. Weitere Details finden Sie in dieser Antwort
quelle
Aufgrund der Speicherverwaltung ist es nützlich, zwischen Mitgliedsvariablen und lokalen Variablen zu unterscheiden. Im Allgemeinen sollten Heap-zugewiesene Mitgliedsvariablen im Destruktor zerstört werden, während Heap-zugewiesene lokale Variablen in diesem Bereich zerstört werden sollten. Das Anwenden einer Namenskonvention auf Mitgliedsvariablen erleichtert die korrekte Speicherverwaltung.
quelle
Code Complete empfiehlt m_varname für Mitgliedsvariablen.
Obwohl ich die m_-Notation nie für nützlich gehalten hätte, würde ich McConnells Meinung beim Aufbau eines Standards Gewicht verleihen.
quelle
Ich verwende fast nie Präfixe vor meinen Variablennamen. Wenn Sie eine ausreichend anständige IDE verwenden, sollten Sie in der Lage sein, Referenzen leicht umzugestalten und zu finden. Ich verwende sehr klare Namen und habe keine Angst vor langen Variablennamen. Ich hatte auch mit dieser Philosophie nie Probleme mit dem Umfang.
Das einzige Mal, wenn ich ein Präfix verwende, ist in der Signaturzeile. Ich werde einer Methode Parameter mit _ voranstellen, damit ich sie defensiv programmieren kann.
quelle
Sie sollten niemals ein solches Präfix benötigen. Wenn ein solches Präfix Ihnen einen Vorteil bietet, muss Ihr Codierungsstil im Allgemeinen korrigiert werden, und es ist nicht das Präfix, das verhindert, dass Ihr Code klar ist. Typische falsche Variablennamen sind "andere" oder "2". Sie beheben dies nicht, indem Sie verlangen, dass es sich um eine andere handelt, sondern indem Sie den Entwickler dazu bringen, darüber nachzudenken, was diese Variable dort im Kontext dieser Funktion tut. Vielleicht meinte er remoteSide oder newValue oder secondTestListener oder etwas in diesem Bereich.
Es ist ein effektiver Anachronismus, der immer noch zu weit verbreitet ist. Hören Sie auf, Ihren Variablen ein Präfix voranzustellen, und geben Sie ihnen Eigennamen, deren Klarheit widerspiegelt, wie lange sie verwendet werden. Bis zu 5 Zeilen können Sie ohne Verwirrung "i" nennen. Über 50 Zeilen hinaus benötigen Sie einen ziemlich langen Namen.
quelle
Ich mag es, wenn Variablennamen den darin enthaltenen Werten nur eine Bedeutung geben und aus dem Namen herauslassen, wie sie deklariert / implementiert werden. Ich möchte wissen, was der Wert bedeutet, Punkt. Vielleicht habe ich mehr als durchschnittlich Refactoring durchgeführt, aber ich finde, dass das Einbetten, wie etwas in den Namen implementiert wird, das Refactoring mühsamer macht, als es sein muss. Präfixe, die angeben, wo oder wie Objektmitglieder deklariert werden, sind implementierungsspezifisch.
Die meiste Zeit ist es mir egal, ob Rot eine Aufzählung, eine Struktur oder was auch immer ist, und wenn die Funktion so groß ist, dass ich mich nicht erinnern kann, ob Farbe lokal deklariert wurde oder ein Mitglied ist, ist es wahrscheinlich Zeit zu brechen die Funktion in kleinere logische Einheiten.
Wenn Ihre zyklomatische Komplexität so groß ist, dass Sie ohne implementierungsspezifische Hinweise, die in die Namen der Dinge eingebettet sind, nicht verfolgen können, was im Code vor sich geht, müssen Sie höchstwahrscheinlich die Komplexität Ihrer Funktion / Methode reduzieren.
Meistens verwende ich 'this' nur in Konstruktoren und Initialisierern.
quelle
Ich benutze m_ für Mitgliedsvariablen, nur um Intellisense und die damit verbundene IDE-Funktionalität zu nutzen. Wenn ich die Implementierung einer Klasse codiere, kann ich m_ eingeben und die Combobox mit allen m_-Mitgliedern sehen, die zusammen gruppiert sind.
Aber ich könnte natürlich ohne Probleme leben. Es ist nur mein Arbeitsstil.
quelle
this->
Laut C ++ CODING STANDARDS VON JOINT STRIKE FIGHTER AIR VEHICLE (Dezember 2005):
Daher wird das Präfix "m" nicht mehr verwendet, da alle Daten privat sein sollten.
Es ist jedoch eine gute Angewohnheit, das Präfix p vor einem Zeiger zu verwenden, da es sich um eine gefährliche Variable handelt.
quelle
Viele dieser Konventionen stammen aus einer Zeit ohne anspruchsvolle Redakteure. Ich würde empfehlen, eine geeignete IDE zu verwenden, mit der Sie jede Art von Variable einfärben können. Farbe ist bei weitem leichter zu erkennen als jedes Präfix.
Wenn Sie noch mehr Details zu einer Variablen benötigen, sollte jede moderne IDE diese Ihnen anzeigen können, indem Sie das Caret oder den Cursor darüber bewegen. Und wenn Sie eine Variable falsch verwenden (zum Beispiel einen Zeiger mit dem Operator.), Wird ohnehin eine Fehlermeldung angezeigt.
quelle