2008-11-06 4 views

Antwort

39

Ja, es ist legal und funktioniert auf allen Plattformen. Es wird Ihre Mitgliedsvariable a korrekt auf den übergebenen Wert a initialisieren.

Es wird von einigen als sauberer angesehen, sie anders zu benennen, aber nicht alle. Ich persönlich es tatsächlich eine Menge verwenden :)

Initialisierung Listen mit demselben Variablennamen funktioniert, weil die Syntax eines Initialisierung Artikel in einer Initialisierungsliste ist wie folgt:

<Mitglied> (<Wert>)

können Sie überprüfen, was ich oben geschrieben habe durch ein einfaches Programm zu schaffen, das dies tut: (Es wird nicht kompilieren)

class A 
{ 

    A(int a) 
    : a(5)//<--- try to initialize a non member variable to 5 
    { 
    } 
}; 

Sie eine bekommen Kompilierfehler so etwas wie: A hat kein Feld namens 'a'.


Auf einer seitlichen Anmerkung:

Ein Grund, warum Sie nicht möchten den gleichen Mitgliedsnamen verwenden als Parameter Name, den Sie auf die folgende wäre anfälliger ist:

class A 
{ 

    A(int myVarriable) 
    : myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly 
    { 
    } 
    int myVariable; 
}; 

Auf einer seitlichen Anmerkung (2):

ein Grund, warum y ou kann wollen das gleiche Elementnamen verwenden als Parameter Name, den Sie ist wäre weniger anfällig für die folgenden:

class A 
{ 

    A(int myVariable_) 
    { 
    //<-- do something with _myVariable, oops _myVariable wasn't initialized yet 
    ... 
    _myVariable = myVariable_; 
    } 
    int _myVariable; 
}; 

Dies auch mit großen Initialisierungsliste passieren könnte, und Sie verwenden _myVariable, bevor es in der Initialisierung initialisiert Liste.

+2

Es ist eine Frage des Geschmacks. Ich bevorzuge es, identischen Namen identische Namen zu geben. Deshalb benutze ich Namespaces weit. –

+1

Sehr oft für private Felder finden Sie Namen wie "a_" oder "_a". –

+0

Elementvariablen sind oft m_a oder _a. Bereichsvariablen sind oft a_. –

4

Legal: Ja, wie von Brian erklärt, Compiler weiß der Name in der Initialisierungsliste zu erwarten, muss ein Mitglied sein (oder eine Basisklasse), nichts anderes.

Guter Stil: höchstwahrscheinlich nicht - für viele Programmierer (einschließlich Ihnen scheint es) das Ergebnis ist nicht offensichtlich. Die Verwendung eines anderen Namens für den Parameter behält den Code für legal und macht ihn gleichzeitig zu einem guten Stil.

würde ich es vorziehen, einige schreiben:

class C { 
    T a_; 
public: 
    C(T a): a_(a) {} 
}; 


class C { 
T a; 
public: 
C(T value): a(value) {} 
}; 
+1

Nein, für mich ist das Ergebnis offensichtlich. Wenn ein (a) Konstrukt legal ist, dann bedeutet das definitiv, dass diese "a" verschieden sind.Ich war mir nur nicht sicher, ob es in C++ wirklich legal ist. –

+1

Sie müssen sehr vorsichtig sein, wenn Sie Kennungen mit führenden Unterstrichen verwenden, um Konflikte mit der Implementierung zu vermeiden. Sie sind in der Tat in Ordnung, wenn es von einem Kleinbuchstaben gefolgt wird, wie hier, aber es ist allgemein am besten, sie zu vermeiden. Siehe Frage 228783 für mehr. – tragomaskhalos

+0

Es ist eine Frage der Präferenz, es gibt Vorteile in beide Richtungen. –

7

wenn der formale Parameter und das Element benannt gleichen dann für die Verwendung dieser Zeiger im Konstruktor Vorsicht vor dem Membervariable zu verwenden

class C { 
    T a; 
public: 
    C(T a): a(a) { 
this->a.sort ;//correct 
a.sort();//will not affect the actual member variable 
} 
}; 
+0

Hmm ... das scheint ein guter Grund zu sein, sie anders zu benennen. Guter Punkt. –

+0

Dies ist ein guter Grund, 'const' für unveränderliche Input-by-Value-Parameter in Implementierungen von Funktionen zu verwenden. – Ruslan

16

Einen Die Dinge, die zu Verwirrung über dieses Thema führen können, ist, wie Variablen vom Compiler priorisiert werden.wenn einer der Konstruktorargumente Um zum Beispiel den gleichen Namen wie ein Klassenmitglied hat könnten Sie die folgenden in der Initialisierungsliste schreiben:

MyClass(int a) : a(a) 
{ 
} 

Aber hat der obige Code haben die gleiche Wirkung wie das?

MyClass(int a) 
{ 
    a=a; 
} 

Die Antwort ist nein. Immer wenn Sie "a" in den Rumpf des Konstruktors eingeben, sucht der Compiler zuerst nach einer lokalen Variablen oder einem Konstruktorargument mit dem Namen "a", und nur wenn er keinen findet, sucht er nach einem Klassenmember namens "a". (und wenn keine verfügbar ist, sucht sie nach einer globalen Variablen, die übrigens "a" genannt wird). Das Ergebnis ist, dass das obige Statement "a = a" den Wert, der in Argument "a" gespeichert ist, dem Argument "a" zuweist, was es zu einer nutzlosen Aussage macht.

Um den Wert des Arguments der Klasse Mitglied „a“ Sie den Compiler informieren müssen zuweisen, dass Sie einen Wert innerhalb diese Klasse Instanz verweisen:

MyClass(int a) 
{ 
    this->a=a; 
} 

Gut, aber was wenn Sie so etwas wie dies tun (beachten Sie, dass es kein Argument „a“ bezeichnet ist):

MyClass() : a(a) 
{ 
} 

Nun, in diesem Fall der Compiler für ein Argument aussehen würde zunächst „a“ genannt und wenn es entdeckt, dass Da war nichts, das wäre ein den Wert des Klassenmembers "a" dem Klassenmember "a" zuweisen, was effektiv nichts bewirken würde.

Schließlich sollen Sie wissen, dass Sie nur die Werte an den Teilnehmer in der Initialisierungsliste zuordnen können, so dass die folgenden wird einen Fehler erzeugen:

MyClass(int x) : x(100) // error: the class doesn't have a member called "x" 
{ 
} 
2

Das Problem mit dieser Praxis, rechtlichen, obwohl es sein kann, ist, dass Compiler berücksichtigen die Variablen, die bei Verwendung von -Wshadow beschattet werden, und sie verschleiern diese Warnungen in anderem Code.

Darüber hinaus machen Sie in einem nicht-trivialen Konstruktor einen Fehler und vergessen, dies vor den Namen des Elements zu setzen.

Java erlaubt dies nicht einmal. Es ist eine schlechte Übung und sollte vermieden werden.