Was ist die Membervariablen Liste nach dem Doppelpunkt in einem Konstruktor gut?

StackOverflow https://stackoverflow.com/questions/210616

  •  03-07-2019
  •  | 
  •  

Frage

Ich lese diesen C ++ Open-Source-Code und ich kam zu einem Konstruktor, aber ich verstehe es nicht (im Grunde, weil ich nicht weiß, C ++: P)

Ich verstehe, C und Java sehr gut.

 TransparentObject::TransparentObject( int w, int x, int y, int z ) : 
     _someMethod( 0 ),
     _someOtherMethod( 0 ),
     _someOtherOtherMethod( 0 ),
     _someMethodX( 0 ) 
  {
       int bla;
       int bla;
  }

Was kann ich „ableiten“ Die erste Zeile deklariert nur die construtor Namen, die „::“ klingt wie „gehört“ zu mir. Und der Code zwischen {} ist der Konstruktor Körper selbst ein.

ich „denken“, was nach dem paremeters und dem ersten „{“ sind wie Methoden Standardparameter oder so etwas, aber ich weiß nicht eine vernünftige Erklärung, die im Internet finden. Die meisten der C ++ Konstruktoren, die ich in den Beispielen zu finden sind nahezu identisch mit denen in Java.

Ich bin ich direkt in meinen Annahmen? „::“ ist wie gehört, und die Liste nach params und Körper sind wie „default args“ oder so etwas?

UPDATE: Danke für die Antworten. Diese können Methoden genannt werden? (Ich glaube nicht) und was ist der Unterschied von ihnen innerhalb der Konstruktorrumpf rufen

War es hilfreich?

Lösung

Der häufigste Fall ist dies:

class foo{
private:
    int x;
    int y;
public:
    foo(int _x, int _y) : x(_x), y(_y) {}
}

Dies wird x und y auf die Werte, die in _x und _y in dem Konstruktor Parameter angegeben werden. Dies ist oft der beste Weg, um alle Objekte zu konstruieren, die als Datenelemente deklariert werden.

Es ist auch möglich, dass Sie bei Konstruktorverkettung suchen:

class foo : public bar{
    foo(int x, int y) : bar(x, y) {}
};

In diesem Fall den Konstruktor der Klasse den Konstruktor der Basisklasse aufrufen und die Werte x und y passieren.

Um die Funktion sezieren noch weiter:

TransparentObject::TransparentObject( int w, int x, int y, int z ) : 
   _someMethod( 0 ),
   _someOtherMethod( 0 ),
   _someOtherOtherMethod( 0 ),
   _someMethodX( 0 ) 
{
     int bla;
     int bla;
}

Der ::-Operator wird der Bereichsauflösungsoperator genannt. Es besteht im Wesentlichen zeigt nur, dass TransparentObject Mitglied TransparentObject ist. Zweitens sind Sie richtig in der Annahme, dass der Körper des Konstruktors in den geschweiften Klammern auftritt.

  

UPDATE: Danke für die Antworten. Diese können Methoden genannt werden? (Ich glaube nicht) und was ist der Unterschied von ihnen innerhalb der Konstruktorrumpf rufen

Es gibt viel mehr Informationen zu diesem Thema ist, als ich es könnte jemals geben Sie a href = „http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6“ rel <=“ noreferrer "> hier . Der häufigste Bereich, in dem Sie initializer Listen zu verwenden ist, wenn Sie einen Verweis oder eine const sind initialisiert, da diese Variablen einen Wert unmittelbar nach der Erstellung gegeben werden müssen.

Andere Tipps

Sie sind ziemlich nah dran. Die erste Zeile ist die Erklärung. Das Etikett links von der :: ist der Klassenname und für sie einen Konstruktor sein, muss der Name der Funktion die gleiche wie die Klassennamen sein.

TransparentObject::TransparentObject( int w, int x, int y, int z )

In C ++ können Sie optional einen Doppelpunkt und einige Anfangswerte für Membervariablen vor dem Start der Funktion Körper. Diese Technik muss verwendet werden, wenn Sie initialzing jedes const Variablen oder Übergabe von Parametern an einen Oberklassenkonstruktors.

: 
 _someMethod( 0 ),
 _someOtherMethod( 0 ),
 _someOtherOtherMethod( 0 ),
 _someMethodX( 0 )

Und dann kommt der Körper des Konstrukteurs in geschweiften Klammern.

{
   int bla;
   int bla;
}

:: Eigentlich bedeutet enthält (Kommentare zur Verdeutlichung sehen), aber die _someMethods und so ist her, was ein Initialisierungsliste . Es gibt jede Menge Informationen auf den Link =]

EDIT:. Sorry, mein erster Satz ist falsch - die Kommentare sehen

Ja, :: ist der C ++ Scoping-Operator, der Sie die Compiler kann sagen, was die Funktion gehört. Mit a:., Nachdem der Konstruktor Deklaration beginnt, was eine Initialisierung Liste aufgerufen wird,

Der Code zwischen der Argumentliste und dem {}s gibt die Initialisierung (einige) die Klasse Mitglieder.

Initialisierung als auf Zuweisung Gegensatz --- sie sind verschiedene Dinge --- so sind diese alle Anrufe an Konstrukteuren.

Sie sind richtig. Es ist ein Weg, um die Standardwerte für die Klassenvariablen zu setzen. Ich bin nicht allzu vertraut mit dem genauen Unterschied zwischen ihnen nach dem Aufsetzen. Und in dem Funktionskörper

Es gibt in der Regel einige gute Gründe, eine Initialisierung Liste zu verwenden. Zum einen können Sie nicht Membervariablen gesetzt, die Verweise außerhalb der Initialisierungsliste des Konstruktors sind. Auch wenn eine Membervariable bestimmte Argumente an seinen eigenen Konstruktor muss, müssen Sie sie in hier passieren. Vergleichen Sie dies:

class A
{
public:
  A();
private:
  B _b;
  C& _c;
};

A::A( C& someC )
{
  _c = someC; // this is illegal and won't compile. _c has to be initialized before we get inside the braces
  _b = B(NULL, 5, "hello"); // this is not illegal, but B might not have a default constructor or could have a very 
                            // expensive construction that shouldn't be done more than once
}

zu dieser Version:

A::A( C& someC )
: _b(NULL, 5, "hello") // ok, initializing _b by passing these arguments to its constructor
, _c( someC ) // this reference to some instance of C is correctly initialized now
{}

Ohne mit der initialiser Liste alle Mitglieder der Klasse einfach ihre Standard Konstruktor aufgerufen, so dies der einzige Ort ist, die Sie steuern können die Konstruktor aufgerufen wird (für nicht-dynamisch zugewiesenen Mitglieder). Das gleiche gilt für welche übergeordnete Klasse Konstruktor aufgerufen werden.

Klasse members „initialisiert“ innerhalb des Körpers des Konstruktors (das heißt zwischen den {} die Zahnspange = Operator) ist technisch nicht Initialisierung es eine Zuordnung ist. Für die Klassen mit einem nicht-triviale Konstruktor / Destruktor kann es teuer sein Konstrukt auf Standard und dann durch Zuordnung auf diese Weise zu modifizieren. Für Referenzelemente Sie muss die initialiser Liste verwenden, da sie nicht über den Zuweisungsoperator geändert werden kann.

Wenn das Element (oder Elternklasse) nicht ein Standard-Konstruktor dann einen entsprechenden Konstruktor in der initialiser Liste angeben, andernfalls wird den Compiler verursacht einen Fehler zu erzeugen. Andernfalls wird der Compiler den Standard-Konstruktor einfügen nennt sich. Für Typen gebaut dies tut nichts so haben Sie es Müll Werte.

Beachten Sie, dass die Reihenfolge, in der die Mitglieder in der initialiser Liste angeben die Bestellung nicht beeinflussen, in dem sie aufgerufen werden . Es ist immer die übergeordnete Klasse Konstruktor (falls vorhanden) zuerst, dann die Klassenmitglieder in der Reihenfolge, in der sie in der Klassendefinition definiert sind. Die Reihenfolge, in der sie in der initialiser Liste gesetzt spielt keine Rolle, und die Quelle des subtilen Fehlers sein kann ...

Im konstruiertes Beispiel unten sieht es aus wie die Absicht m_b mit value zu initialisieren ist dann m_a mit m_b, aber was passiert eigentlich, dass m_a mit m_b initialisiert wird (das ist selbst noch nicht initialisiert), dann wird m_b mit value initialisiert. m_b wird nur enthalten Müll!

struct BadInitialiserListExample
{
    BadInitialiserListExample(int value) :
        m_b(value),
        m_a(m_b)      // <-- *BUG* this is actually executed first due to ordering below!
    {
    }

    int    m_a;
    int    m_b;
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top