Was bedeutet das Variablenpräfix "m_"?

153

Ich sehe oft m_Präfix für Variablen verwendet ( m_World, m_Sprites, ...) in Tutorials, Beispielen und anderem Code in erster Linie im Zusammenhang mit der Spieleentwicklung.

Warum fügen Leute m_Variablen Präfixe hinzu?

Kravemir
quelle
18
Bevor Sie sinnlos mit ungarischer Notation nachziehen, überprüfen Sie bitte die Geschichte, was die ungarische Notation wirklich ist. Weil das Benennen eines int iCounter einfach sinnlos ist. Es ist jedoch sinnvoll, int xAnnotationPos und yAnnotationPos zu benennen. Verwenden Sie die semantische Version.
AkselK
Manchmal stellen importierte Module Funktionen und Variablen voran, sodass Sie sie weniger wahrscheinlich mit Ihrem eigenen Code überschreiben. Es ist eine Möglichkeit, Namen für eine bestimmte Verwendung zu reservieren.
EarthmeLon
3
Während die "ungarische" Notation oft bösartig verspottet wird, hat der besondere Geschmack, der den variablen Umfang kennzeichnet, einige echte Vorteile. Zusätzlich zum Identifizieren des Bereichs der Variablen werden Namenskollisionen verhindert, wenn ein lokaler, ein Parameter und ein Mitglied alle dieselbe Absicht und damit denselben "semantischen" Namen haben. Dies kann die Wartung großer Codebasen einfacher und weniger fehleranfällig machen.
Hot Licks
8
Es gibt Argumente für und gegen jeden Kodierungsstandard, aber die Frage fragt eindeutig, wozu sie gut sind m_, doch die Hälfte der Antworten hier ist ein Kommentar darüber, warum jeder denkt, sein aktueller Favorit sei der beste.
cz

Antworten:

107

Dies ist eine typische Programmierpraxis zum Definieren von Variablen, die Mitgliedsvariablen sind. Wenn Sie sie später verwenden, müssen Sie nicht sehen, wo sie definiert sind, um ihren Umfang zu kennen. Dies ist auch großartig, wenn Sie den Umfang bereits kennen und etwas wie IntelliSense verwenden . Sie können damit beginnen m_und eine Liste aller Ihrer Mitgliedsvariablen wird angezeigt. Ein Teil der ungarischen Notation, siehe den Teil über den Umfang in den Beispielen hier .

MichaelHouse
quelle
51
Als schlechtestes Argument für eine Namenskonvention können Sie einfach Strg + Leertaste für Intellisense drücken.
Orlp
11
@nightcracker Obwohl mir das Präfix nicht gefällt, meint er damit, dass Sie bei Eingabe von m_ und dann "STRG + LEERTASTE" (sofern es nicht automatisch ist) eine Liste erhalten, die nur Ihre Mitglieder enthält. Nicht gerade ein guter Grund, aber es ist ein Plus.
Sidar
13
Erwähnenswert ist, dass es viele andere mehr oder weniger übliche Methoden gibt, um dasselbe zu tun. "m_variable", "m_Variable", "mVariable", "_variable", "_Variable" ... welcher Weg "am besten" oder "richtig" ist (oder ob er überhaupt zu tun ist), ist ein ebenso umstrittenes und fruchtloses Argument wie " Leerzeichen gegen Tabulatoren '. :)
Trevor Powell
49
Ich bevorzuge die Verwendung von "this->" - macht "m_" irgendwie überflüssig und ist sogar noch besser, da es vom Compiler erzwungen wird (theoretisch kann man "m_" für jeden Variablentyp platzieren; das kann man mit "this-> nicht" "). Ein Teil von mir wünscht sich, dass C ++ nur standardisiert, um "this->" obligatorisch zu machen. Aber das geht mehr in die Welt der Diskussion als eine Antwort.
3
@LaurentCouvidou, Sie können nicht wirklich erzwingen, dass Entwickler Mitgliedsvariablen erstellen, denen m_entweder ein Präfix vorangestellt ist .
SomeWritesReserved
93

In Clean Code: Ein Handbuch für agiles Software-Handwerk gibt es eine explizite Empfehlung gegen die Verwendung dieses Präfixes:

Sie müssen Mitgliedsvariablen auch keine Präfixe mehr voranstellen m_. Ihre Klassen und Funktionen sollten klein genug sein, dass Sie sie nicht benötigen.

Es gibt auch ein Beispiel (C # -Code) dafür:

Schlechte Praxis:

public class Part
{
    private String m_dsc; // The textual description

    void SetName(string name)
    {
        m_dsc = name;
    }
}

Gute Übung:

public class Part
{
    private String description;

    void SetDescription(string description)
    {
        this.description = description;
    }
}

Wir rechnen mit Sprachkonstrukten zu Elementvariablen im Fall ausdrücklich Mehrdeutigkeit beziehen ( das heißt , descriptionMitglied und descriptionParameter): this.

InfZero
quelle
6
Der Wortlaut könnte lauten: "Es gibt eine explizite Empfehlung GEGEN die Verwendung dieses Präfixes:"
Xofo
Ich bin so froh, dass jemand es geschrieben hat
dmitreyg
Ein weiterer Grund ist, dass in Java getter / setter als getName / setName angenommen wird. GetM_name ist also schlecht und Sie müssen sie einzeln behandeln.
Leon
Danke, dass du das geschrieben hast. Ich wollte nur darauf hinweisen, dass das von Ihnen zitierte Buch seit August 2008 herauskommt - und ich finde diese schlechte Praxis heute (2019) immer noch in neuem Code.
Alexlomba87
20

Dies ist in C ++ üblich. Dies liegt daran, dass Sie in C ++ nicht denselben Namen für die Elementfunktion und die Elementvariable haben können und Getterfunktionen häufig ohne das Präfix "get" benannt werden.

class Person
{
   public:
      std::string name() const;

   private:
      std::string name; // This would lead to a compilation error.
      std::string m_name; // OK.
};

main.cpp:9:19: error: duplicate member 'name'
      std::string name;
                  ^
main.cpp:6:19: note: previous declaration is here
      std::string name() const;
                  ^
1 error generated.

http://coliru.stacked-crooked.com/a/f38e7dbb047687ad

"m_" gibt für das "Mitglied" an. Das Präfix "_" ist ebenfalls üblich.

Sie sollten es nicht in Programmiersprachen verwenden, die dieses Problem durch Verwendung unterschiedlicher Konventionen / Grammatik lösen.

doc
quelle
11

Das m_Präfix wird häufig für Mitgliedsvariablen verwendet. Ich denke, sein Hauptvorteil besteht darin, dass es dabei hilft, eine klare Unterscheidung zwischen einer öffentlichen Eigenschaft und der privaten Mitgliedsvariablen zu treffen, die sie unterstützt:

int m_something

public int Something => this.m_something; 

Es kann hilfreich sein, eine konsistente Namenskonvention für das Sichern von Variablen zu haben, und das m_Präfix ist eine Möglichkeit, dies zu tun - eine, die in Sprachen ohne Berücksichtigung der Groß- und Kleinschreibung funktioniert.

Wie nützlich dies ist, hängt von den Sprachen und Tools ab, die Sie verwenden. Moderne IDEs mit starken Refactor-Tools und Intellisense benötigen weniger Konventionen wie diese, und dies ist sicherlich nicht die einzige Möglichkeit, dies zu tun, aber es lohnt sich auf jeden Fall, sich der Praxis bewusst zu sein.

Keith
quelle
5
Wenn Sie this.in Ihrer Sprache schreiben müssen, m_ist das wirklich nutzlos.
Ruslan
@Ruslan das m_ist, um es von der Eigenschaft zu unterscheiden, die es sichert - also this.Somethingfür die Eigenschaft vs this.m_somethingfür das unterstützende Mitglied. Es ist keine Konvention, die ich selbst bevorzuge, aber ich habe meistens gesehen, dass sie für unempfindliche Sprachen (wie VB) verwendet wird.
Keith
1
Warum nicht this.Somethingfür die Immobilie und this.somethingfür die Unterstützung? Oder this._somethingfür die Unterstützung? this.m_somethingist redundant. Ich benutze, _somethingdamit ich es nicht versehentlich Something
tippe,
@AustinWBryan siehe meinen vorherigen Kommentar zu Sprachen, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird. Ja, ein _Präfix allein würde den Job machen, ist aber m_die Konvention. Es ist nicht eines, das ich persönlich verwenden würde, aber wenn Sie es im Code sehen, war das die Absicht des Autors.
Keith
7

Wie in den anderen Antworten angegeben, wird das m_Präfix verwendet, um anzuzeigen, dass eine Variable ein Klassenmitglied ist. Dies unterscheidet sich von der ungarischen Notation, da sie nicht den Typ der Variablen, sondern ihren Kontext angibt.

Ich verwende m_in C ++, aber nicht in einigen anderen Sprachen, in denen 'dies' oder 'selbst' obligatorisch ist. Ich mag es nicht, wenn 'this->' mit C ++ verwendet wird, weil es den Code überfüllt.

Eine andere Antwort m_dsclautet "schlechte Praxis" und "Beschreibung". ist "gute Praxis", aber dies ist ein roter Hering, weil das Problem dort die Abkürzung ist.

Eine andere Antwort besagt, dass durch Eingabe thisIntelliSense angezeigt wird, aber jede gute IDE über einen Hotkey verfügt, mit dem IntelliSense für die aktuellen Klassenmitglieder angezeigt wird.

Quentin 2
quelle
"aber das ist ein roter Hering" - Guter Punkt. Ein fairer Vergleich wäre m_descriptionvs description.
Schlacht
3

Wie in vielen anderen Antworten angegeben, ist m_ ein Präfix, das Mitgliedsvariablen bezeichnet. Es wird / wurde häufig in der C ++ - Welt verwendet und auch in andere Sprachen, einschließlich Java, weitergegeben.

In einer modernen IDE ist es vollständig redundant, da die Syntaxhervorhebung deutlich macht, welche Variablen lokal und welche Mitglieder sind . Zu dem Zeitpunkt, als die Syntaxhervorhebung Ende der 90er Jahre erschien, gab es die Konvention jedoch schon seit vielen Jahren und sie war fest verankert (zumindest in der C ++ - Welt).

Ich weiß nicht, auf welche Tutorials Sie sich beziehen, aber ich vermute, dass sie die Konvention aufgrund eines von zwei Faktoren verwenden:

  • Es handelt sich um C ++ - Tutorials, die von Personen geschrieben wurden, die an die m_-Konvention gewöhnt sind, und / oder ...
  • Sie schreiben Code in einfachem (monospaced) Text ohne Syntaxhervorhebung, daher ist die m_-Konvention nützlich, um die Beispiele klarer zu machen.
Sergut
quelle
Ein Beispiel könnte dies sein: wiki.qt.io/How_to_Use_QSettings Da der Qt Creator Hervorhebungen verwendet, wird möglicherweise die erste Vermutung angezeigt . Ein bisschen anders könnte eine andere Konvention sein, die _object () für private Objekte einer Klasse und p_variable verwendet, wenn es sich um einen Zeiger handelt, da beide, wie ich weiß, nicht hervorgehoben sind und für mich sinnvoll erscheinen, sie zu verwenden.
Ivanovic
3

Lockheed Martin verwendet ein Namensschema mit drei Präfixen, mit dem man wunderbar arbeiten konnte, insbesondere beim Lesen des Codes anderer.

   Scope          Reference Type(*Case-by-Case)   Type

   member   m     pointer p                       integer n
   argument a     reference r                     short   n
   local    l                                     float   f
                                                  double  f
                                                  boolean b

So...

int A::methodCall(float af_Argument1, int* apn_Arg2)
{
    lpn_Temp = apn_Arg2;
    mpf_Oops = lpn_Temp;  // Here I can see I made a mistake, I should not assign an int* to a float*
}

Nehmen Sie es für das, was es wert ist.

jiveturkey
quelle
Genial. Danke für das "Beispiel". Es ist sehr praktisch, wenn Sie 200.000 Codezeilen bearbeiten.
Jiveturkey
1
Keine Notwendigkeit, defensiv zu werden. Ich versuche ehrlich, Ihnen zu helfen, indem ich Ihnen zeige, dass Ihre Antwort einen Fehler enthält. Lassen Sie mich dann klarer sein: Es spielt keine Rolle, ob Sie 5 oder 200000 Codezeilen haben: Der Compiler lässt Sie keine Zuweisung mit inkompatiblen Zeigertypen vornehmen. Der im Kommentar gemachte Punkt ist also umstritten.
Cássio Renan
Wollte nicht als defensiv abschneiden. Es tut uns leid.
Jiveturkey
Es ist eine Variation der ungarischen Notation, die in modernen Sprachen keinen Sinn ergibt ...
Dok.
2

Um die aktuellen Antworten zu vervollständigen und da die Frage nicht sprachspezifisch ist, verwenden einige C-Projekte das Präfix m_, um globale Variablen zu definieren, die für eine Datei spezifisch sind - und g_für globale Variablen, deren Umfang größer ist als die Datei, die sie definiert haben.
In diesem Fall sollten globale Variablen, die mit dem Präfix m_ definiert sind, definiert werden als static.

Ein Beispiel für ein Projekt, das diese Konvention verwendet, finden Sie unter EDK2-Codierungskonvention (eine UEFI-Open-Source-Implementierung) .

OlivierM
quelle
1

Ein Argument, das ich noch nicht gesehen habe, ist, dass ein Präfix wie m_dieses verwendet werden kann, um zu verhindern, dass Namen mit #define'd-Makros kollidieren .

Regex-Suche nach #define [a-z][A-Za-z0-9_]*[^(]In /usr/include/term.haus Flüchen / Flüchen.

yyny
quelle