Ich könnte mir vorstellen, dass diese Frage bereits gestellt wurde, aber ich konnte tatsächlich keine passende Lösung finden, also bitte entschuldigen Sie, wenn das eine überflüssige Frage ist.
Ich habe eine benutzerdefinierte Klasse
%Vor% Jetzt habe ich eine andere benutzerdefinierte Klasse, die ein Mitglied vom Typ myClass_A
Nun möchte myFunction_B()
die Methode myFunction_A()
von m_instance
kinda wie folgt aufrufen:
Nun, wenn ich meinen Code kompiliere (was im Grunde wie das Beispiel ist, das ich oben gepostet habe), wird es ohne irgendwelche Warnungen oder Fehler gelingen. Also meine Fragen wären:
A. Wird der Konstruktor in diesem Beispiel aufgerufen?
B. Kann ich Methoden von einem nicht initialisierten Objekt aufrufen?
C. Angenommen, der Konstruktor wird nicht aufgerufen, aber ich kann immer noch die Methoden von diesem Objekt aufrufen - & gt; Das bedeutet noch, dass die Mitglieder meiner Klasse nicht initialisiert sind?
Tut mir leid, wenn diese Fragen irgendwie dumm sind, aber ich habe das Gefühl, dass ich gerade jetzt langsam bin.
Das sind sehr gute und wichtige Fragen.
Betreffend A:
Bevor Sie den Rumpf Ihres Konstruktors ausführen, generiert C ++ Code, der automatisch den Standardkonstruktor aller aggregierten (d. h. Mitglieds-) Objekte Ihrer Klasse aufruft. Im Grunde wird der folgende Code umgewandelt:
%Vor%in den folgenden Code:
%Vor% Die beiden Zeilen, die der Compiler automatisch eingefügt hat, heißen Initialisierungsliste und ruft den Standardkonstruktor auf von jedem Aggregatobjekt vor wird der Rumpf Ihres Konstruktors ausgeführt. Bitte beachten Sie, dass der zweite, m_pInstance()
den "Standardkonstruktor von Zeiger " aufruft, der einen nicht initialisierten Zeiger erstellt ; das ist fast immer nicht das was du willst. Siehe unten, wie Sie das beheben können.
Nehmen wir nun an, dass der Konstruktor von myClass_A
die Signatur myClass_A(int someNumber)
hat, d. h. er benötigt ein Argument. Dann kann C ++ nicht die Initialisierungsliste für myClass_B
automatisch generieren, da es nicht weiß, welche Zahl den Konstruktor von myClass_A
übergeben soll. Es wird einen Compilerfehler bei dir auslösen, der sich wahrscheinlich über einen fehlenden Standardkonstruktor für myClass_A
beschweren wird. Sie müssen die Initialisiererliste selbst schreiben, zum Beispiel:
Dies ist der korrekte Code, der myClass_A
-Konstruktor mit dem Wert 21 für den Parameter someNumber
aufruft. Dies zeigt auch, wie Sie einen Zeiger korrekt initialisieren: Lassen Sie ihn auf ein neu zugewiesenes Objekt zeigen.
In Bezug auf B:
Anders als einige andere sagen, können Sie! (Probieren Sie es aus)
Aber es führt zu unerwartetem Verhalten, das nicht das ist, was Sie wollen. (Einschließlich, dass es tun könnte, was Sie nur wollen, wenn die Planeten richtig ausgerichtet sind.) Es wird höchstwahrscheinlich abstürzen, aber es ist nicht garantiert, dass es abstürzt. Dies kann zu langen Debugging-Nächten führen. Wenn Ihr Compiler intelligent ist, erkennt er dies möglicherweise und warnt Sie, aber Sie erhalten keinen Fehler.
Beachten Sie auch, dass für Non-Pointer-Aggregatobjekte, die einen Standardkonstruktor haben, der Standardkonstruktor aufgerufen wird und Sie alle gut sind. Das Problem tritt auf, wenn Sie eingebaute Typen oder Zeiger verwenden. Dies ist die Verwendung von nicht initialisierten Variablen und ist eine der häufigsten Ursachen für einen Fehler. Wenn Ihr Code etwas total Seltsames tut, überprüfen Sie immer, ob Sie alle Ihre Variablen initialisiert haben. Es sollte ein Reflex werden, einen Eintrag in die Initialisierungsliste für jede Mitgliedsvariable zu setzen, selbst wenn sie den Standardkonstruktor aufruft. Macht die Dinge klar.
In Bezug auf C:
Ja. Siehe B für Details. Das Interessante daran ist, dass Ihre Methode garantiert funktioniert, wenn die Methode, die Sie aufrufen, nicht den "This" -Zeiger verwendet (dies beinhaltet, keine Attributvariable zu verwenden und keine Methode aufzurufen, die eine Attributvariable verwendet). Was passiert, wenn Sie eine Methode für ein nicht initialisiertes Objekt aufrufen, ist, dass das "dieses" Objekt innerhalb der Methode (d. H. Alle Attributvariablen) zufälliger Speicher ist. Der Code der Methode wird ausgeführt, verwendet aber zufälligen Speicher und das ist was fehlschlägt.
Ich hoffe, das klärt die Dinge ein wenig auf.
Wird der Konstruktor in diesem Beispiel aufgerufen?
Ja
Die Konstruktoren für myClass_B
wurden aufgerufen, nachdem der Aufruf des Konstruktors myClass_A()
abgeschlossen ist.
Normalerweise würden Sie das myClass_B
-Objekt im Konstruktor von my_class_A
mit einem
initialisieren. member-syntax-in-the-constructor / 8523361 # 8523361 "> Mitgliederinitialisierungsliste .
Kann ich tatsächlich Methoden von einem nicht initialisierten Objekt aufrufen?
Wenn ein Objekt erstellt wird, wird sein Konstruktor immer aufgerufen. Wenn Sie kein Objekt konstruieren, können Sie keine Methode dafür aufrufen. Dies ist der Zweck von Konstruktoren, ein Objekt zu erstellen und es zu initialisieren.
Wenn Sie also ein Objekt haben, ist es niemals uninitialisiert.
Wenn Sie auf Zeiger verweisen, sind Zeiger für sich keine Objekte, die auf ein gültiges oder ungültiges Objekt verweisen können. Wenn Sie einen Zeiger (zum Aufrufen einer Elementfunktion oder was auch immer) nicht auf ein gültiges Objekt zeigen, führt dies zu Undefiniertes Verhalten .
Angenommen, der Konstruktor wird nicht aufgerufen, aber ich kann immer noch die Methoden von diesem Objekt aufrufen - & gt; Das bedeutet noch, dass die Mitglieder meiner Klasse nicht initialisiert sind?
Antwort auf die zweite Frage beantwortet dies.
Klassenmitglieder werden automatisch vom Compiler mithilfe des Standardkonstruktors initialisiert, sofern Sie nicht anders im Konstruktor Ihrer eigenen Klasse angeben Initialisierungsliste . Also ja, der Konstruktor wird aufgerufen.
Sie können dies selbst testen, indem Sie:
Wenn Sie Methoden aufrufen oder auf Member eines Objekts zugreifen, das nicht initialisiert wurde oder bereits zerstört wurde (beide Szenarien können erstellt werden), haben Sie undefiniertes Verhalten .
A. Der Konstruktor für Ihre Klasse myClass_A wird aufgerufen, sobald das Objekt der Klasse myClass_B instanziiert wird.
B. Sie können z. B. keine Methoden von nicht-entialisierten Objekten aufrufen
%Vor%wird eine Ausnahme auslösen.
C. Sie können eine Methode niemals erfolgreich aufrufen, ohne dass das Objekt vollständig aufgebaut ist.
Tags und Links c++ constructor initialization