Frage

Auf diese Frage gibt es hier bereits eine Antwort:

Ich habe es mit einer großen Codebasis zu tun, die durchgehend das folgende Konstrukt verwendet

class MyClass
{
public:
  void f(int x);
private:
  int x;
};


void MyClass::f(int x)
{
'
'
  this->x = x;
'
'
}

Persönlich habe ich immer die Form verwendet und bevorzuge sie daher

class MyClass
{
public:
  void f(int x);
private:
  int _x;
};


void MyClass::f(int x)
{
'
'
  _x = x;
'
'
}

Die Gründe, warum ich Letzteres bevorzuge, sind, dass es prägnanter ist (weniger Code = weniger potenzielle Fehler) und dass ich es nicht mag, mehrere Variablen mit demselben Namen gleichzeitig im Gültigkeitsbereich zu haben, wo ich das vermeiden kann.Allerdings sehe ich die frühere Verwendung heutzutage immer häufiger.Gibt es einen Vorteil des zweiten Ansatzes, der mir nicht bekannt ist?(z.B.Auswirkung auf die Kompilierungszeit, Verwendung mit Vorlagencode usw.) Sind die Vorteile beider Ansätze signifikant genug, um eine Umgestaltung des anderen zu rechtfertigen?Der Grund dafür ist, dass mir der zweite im Code enthaltene Ansatz zwar nicht gefällt, der Aufwand und das damit verbundene Risiko, weitere Fehler einzuführen, eine Umgestaltung jedoch nicht unbedingt rechtfertigen.

War es hilfreich?

Lösung

Ihre Version ist ein wenig sauberer, aber während Sie gerade dabei sind, würde ich:

  1. Vermeiden Unterstrich: _x in Ordnung ist, bis jemand _MyField wählt, die ein reservierter Name ist. Ein Unterstrich am Anfang von einem Großbuchstaben gefolgt wird nicht als Variablennamen erlaubt. Siehe: Was sind die Regeln über die Verwendung eines Unterstrichs in einer C ++ Kennung
  2. Machen Sie das Attribut privat oder geschützt. Die Änderung sicher ist, wenn es kompiliert, und Sie sicher, dass Ihre Setter verwendet werden
  3. Die this-> Geschichte hat einen Einsatz, zum Beispiel in Templat-Code des Feldname abhängig von Ihrer Art zu machen (kann einige Lookup-Probleme lösen).

ein kleines Beispiel für Namensauflösungen die unter Verwendung eines expliziten this- fixiert sind> (getestet mit g ++ 3.4.3):

#include <iostream>
#include <ostream>

class A
{
public:
  int g_;
  A() : g_(1) {}
  const char* f() { return __FUNCTION__; }
};

const char* f() { return __FUNCTION__; }
int g_ = -1;

template < typename Base >
struct Derived : public Base
{
  void print_conflicts()
  {
    std::cout << f() << std::endl; // Calls ::f()
    std::cout << this->f() << std::endl; // Calls A::f()
    std::cout << g_ << std::endl; // Prints global g_
    std::cout << this->g_ << std::endl; // Prints A::g_
  }
};

int main(int argc, char* argv[])
{
   Derived< A >().print_conflicts();
   return EXIT_SUCCESS;
}

Andere Tipps

Feld Namensgebung hat nichts mit einem codesmell zu tun. Wie Neil sagte, ist Feld Sichtbarkeit der einzige codesmell hier.

Es gibt verschiedene Artikel über Namenskonventionen in C ++:

etc.

Diese Verwendung von 'this' von Microsoft C # Coding-Standards gefördert wird. Es gibt einen guten Code Klarheit und soll ein Standard über die Verwendung von m_ oder _ oder irgendetwas anderes in Membervariablen sein.

Ehrlich gesagt, ich habe wirklich sowieso in Namen unterstreichen nicht mögen, habe ich alle von einem einzigen ‚m‘ meine Mitglieder Präfix.

Viele Leute verwenden dies, weil in ihrer IDE eine Liste der Bezeichner der aktuellen Klasse angezeigt wird.

Ich weiß, dass ich das in BCB tue.

Ich denke, das Beispiel, das Sie mit dem Namenskonflikt liefern, ist eine Ausnahme.In Delphi verwenden Stilrichtlinien jedoch ein Präfix (normalerweise „a“) ​​für Parameter, um genau dies zu vermeiden.

Mein persönliches Gefühl ist, dass eine bestehende Codierung Konvention kämpfen etwas, das Sie nicht tun sollten. Als Sutter / Alexandrescu es in ihrem Buch ‚C ++ Coding Conventions‘ setzt: nicht Kleinkram. Jeder ist in der Lage das eine oder das andere zu lesen, ob es eine führende ‚this->‘ oder ‚_‘ oder was auch immer.

Allerdings Konsistenz in Namenskonventionen ist etwas, das man normalerweise, will so auf eine Konvention an einem gewissen Umfang kleben (zumindest Dateigültigkeitsbereich, idealerweise der gesamte Code-Basis, natürlich) wird als gute Praxis. Sie haben erwähnt, dass dieser Stil über einen größeren Codebasis verwendet wird, so glaube ich, eher eine schlechte Idee wäre eine andere Konvention nachzurüsten.

Wenn Sie schließlich finden es ein guter Grund ist es für die Änderung, tun Sie es nicht manuell tun. Im besten Fall, unterstützt IDE, diese Art von ‚Refactoring‘. Ansonsten ein Skript schreiben, es zu ändern. Suchen & Ersetzen sollte die letzte Option sein. In jedem Fall sollten Sie einen Backup (Source-Control) und eine Art von automatisierter Testanlage haben. Andernfalls werden Sie nicht mit ihm Spaß haben.

‚this‘ auf diese Weise zu verwenden ist IMO nicht ein Code Geruch, sondern ist einfach eine persönliche Präferenz. Es ist daher nicht so wichtig wie die Übereinstimmung mit dem Rest des Codes in dem System ein. Wenn dieser Code inkonsistent ist, könnte man es ändern, um den anderen Code übereinstimmen. Wenn durch Ändern Sie Inkonsistenz mit der Mehrheit der Rest des Codes einführen wird, das ist sehr schlecht und ich würde es allein lassen.

Sie wollen nicht immer in der Lage, Tennis zu spielen, Code zu bekommen, wo jemand rein etwas ändert, um es nur „schön“ aussehen für jemand anderes später mit unterschiedlichem Geschmack zu kommen, die ändert sich dann zurück.

Ich habe immer die m _ Namenskonvention. Obwohl ich „Ungarische Notation“ im Allgemeinen nicht mag, finde ich es sehr nützlich, sehr deutlich zu sehen, ob ich mit Klassenmitgliederdaten arbeite. Auch fand ich 2 identische Variablennamen im gleichen Umfang mit zu fehleranfällig.

Ich bin damit einverstanden. Ich mag es nicht, dass die Namenskonvention - ich ziehe ein, wo es offensichtlich, dass die Unterscheidung zwischen den Mitgliedsvariablen und lokalen Variablen ist. Was passiert, wenn Sie aus dem this verlassen?


class MyClass{
public:  
  int x;  
  void f(int xval);
};
//
void MyClass::f(int xval){  
  x = xval;
}

Meiner Meinung nach diese neigt Unordnung, um den Code zu schreiben, so neige ich dazu, unterschiedliche Variablennamen zu verwenden (abhängig von der Konvention, könnte es ein Unterstrich sein, m _ , was auch immer).

class MyClass
{
public:
  int m_x;
  void f(int p_x);
};


void MyClass::f(int p_x)
{
  m_x = p_x;
}

... ist meine bevorzugte Art und Weise Umfang Präfixe verwenden. m_ für Mitglied, p_ für Parameter (einige Verwendung a_ für Argument statt), g_ für globale und manchmal für die lokale L_ wenn es Lesbarkeit hilft.

Wenn Sie zwei Variablen, die denselben Namen verdienen kann dies helfen, eine Menge und vermeidet auf einige zufällige Variation auf seine Bedeutung machen nur Neudefinition zu vermeiden. Oder noch schlimmer, das gefürchtete 'x2, x3, x4, etc' ...

Es ist mehr normal in C ++ für die Mitglieder auf dem Bau mit initialiser initialisiert werden.

Um das zu tun, Sie einen anderen Namen auf den Namen der Membervariable verwenden.

So, obwohl ich Foo(int x) { this.x = x; } in Java verwenden würde, würde ich nicht in C ++.

Der eigentliche Geruch könnte der Mangel an Einsatz von initialisers und Methoden sein, die nichts anderes tun, als Membervariablen mutiert, anstatt der Verwendung der this -> x selbst.

Wer weiß, warum es allgemeine Praxis ist in jedem C ++ Shop ich in waren verschiedene Namen für Konstruktorargumente an die Mitgliedsvariablen zu verwenden, wenn sie mit initialisers verwenden? gab es einige C ++ Compiler, die es nicht unterstützt hat?

Heute sind die meisten IDE Editoren Farbe Ihre Variablen Klassenmitglieder von lokalen Variablen anzuzeigen. So IMO, weder Präfixe oder 'this->' sollte zur besseren Lesbarkeit erforderlich.

Ich mag es nicht mit „this“, weil es atavistisch ist. Wenn Sie in guten alten C (nicht vergessen, C?) Sind programmiert, und Sie wollen einige der Eigenschaften von OOP imitieren, erstellen Sie eine Struktur mit mehreren Mitgliedern (diese auf die Eigenschaften des Objekts sind analog) und erstellen Sie einen Satz von Funktionen, die alle einen Zeiger auf diese Struktur als ihr erstes Argument (diese auf die Methoden des Objekts analog sind).

(Ich denke, das typedef Syntax korrekt ist, aber es ist eine Weile her ...)

typedef struct _myclass
{
   int _x;
} MyClass;

void f(MyClass this, int x)
{
   this->_x = x;
}

In der Tat glaube ich, ältere C ++ Compiler tatsächlich Ihren Code auf die obige Form kompilieren würde und dann geben sie nur an den C-Compiler. Mit anderen Worten - C ++ zu einem gewissen Grad war nur syntaktischer Zucker. So bin ich nicht sicher, warum jemand in C programmieren möchte ++ und gehen Sie zurück zu explizit „this“ in Code - vielleicht ist es „syntaktischer Nutrisweet“

Wenn Sie ein Problem mit Namenskonventionen haben, können Sie versuchen, so etwas wie das folowing zu verwenden.

class tea
{
public:
    int cup;
    int spoon;
    tea(int cups, int spoons);
};

oder

class tea
{
public:
    int cup;
    int spoon;
    tea(int drink, int sugar);
};

Ich glaube, Sie auf die Idee kam. Es ist die Benennung im Grunde die Variablen anders, aber „gleich“ im logischen Sinne. Ich hoffe, es hilft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top