Konstruktor und Initialisierung von benutzerdefinierten Klassen/Objekte
Ich könnte mir vorstellen das diese Frage schon gefragt wurde, aber ich konnte nicht finden keine passende Lösung, daher bitte Entschuldigung, wenn dies eine redundante Frage.
Habe ich eine eigene Klasse
class myClass_A
{
public:
myClass_A(); //Constructor
myFunction_A(); //Some function from Class A
};
Nun habe ich noch eine custom-Klasse, die hat ein Mitglied aus der Art der myClass_A
class myClass_B
{
public:
myFunction_B(); //Some function from Class B
private:
myClass_A m_instance; //Instance of Class A
}
Nun myFunction_B()
will, rufen Sie die Methode myFunction_A()
aus m_instance
irgendwie so:
myClass_B::myFunction_B()
{
m_instance.myFunction_A();
}
Nun, wenn ich meinen code kompilieren ( das ist im Grunde wie das Beispiel, das ich oben gepostet ) es wird erfolgreich ohne Warnungen oder Fehler. Also meine Fragen wäre:
A. Wird der Konstruktor aufgerufen werden, in diesem Beispiel?
B. Kann ich eigentlich aufrufen von Methoden von ein nicht initialisiertes Objekt?
C. Angenommen, der Konstruktor wird nicht aufgerufen, aber ich kann immer noch die Methoden aufrufen, die das Objekt -> Das bedeutet immer noch, dass die Mitglieder meiner Klasse nicht initialisiert werden?
Sorry, wenn diese Fragen irgendwie dumm, aber ich habe das Gefühl, ich bin langsam auf der Aufnahme jetzt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese sind sehr gute und wichtige Fragen.
Über Eine:
Vor der Ausführung den Hauptteil der Konstruktor der C++ - code generiert, die automatisch die default-Konstruktor aller aggregierten (d.h. member -) Objekte der Klasse. Im Grunde, was es tut, ist, transformieren Sie den folgenden code:
in den folgenden code:
Die zwei Zeilen, die der compiler automatisch eingefügten namens Initialisierungsliste, es ruft den default-Konstruktor für jedes aggregierte Objekt vor der Körper von Ihr Konstruktor ausgeführt wird. Bitte beachten Sie, dass die zweite
m_pInstance()
ruft die "default-Konstruktor Zeiger" das schafft ein nicht initialisierte Zeiger ; dies ist fast immer nicht das, was Sie wollen. Siehe unten auf, wie zu beheben.Lassen Sie uns nun davon ausgehen, dass der Konstruktor von
myClass_A
hat die SignaturmyClass_A(int someNumber)
, d.h. es nimmt ein argument. Dann, C++ nicht generiert automatisch die Initialisierungsliste fürmyClass_B
da es nicht weiß, welche Nummer zu übergebenmyClass_A
's Konstruktor. Er löst einen compiler-Fehler, bei dir, wohl Klagen über eine fehlende Standard-Konstruktor fürmyClass_A
. Sie schreiben, die Initialisierer-Liste auf Ihrem eigenen, zum Beispiel:Dies ist der korrekte code, der Aufrufe
myClass_A
Konstruktor mit dem Wert 21 für den parametersomeNumber
. Dies zeigt auch, wie Sie korrekt initialisieren Sie einen Zeiger: machen Sie den Punkt, um einige neu zugewiesenen Objekt.Bezüglich B:
Im Gegensatz zu einigen anderen sagen, Sie können! (Probieren Sie es aus)
Führt aber zu einem unerwarteten Verhalten, das ist nicht, was Sie wollen. (Einschließlich die, die es könnten tun, was Sie wollen, nur, wenn die Planeten ausgerichtet sind richtig.) Es wird wahrscheinlich Abstürzen, ist aber nicht garantiert, Absturz. Dies kann dazu führen Sie zu einigen langen debugging-Nächte. Wenn dein compiler ist intelligent, er kann dies erkennen und warnen Sie, aber es wird nicht geben Ihnen ein Fehler.
Beachten Sie auch, dass für nicht-Zeiger, zusammengesetzte Objekte, die einen Standard-Konstruktor der Standard-Konstruktor wird genannt werden, und Sie werden alle gut. Das problem kommt, wenn Sie verwenden vordefinierte Datentypen oder Zeigern. Dies ist die Verwendung von nicht initialisierten Variablen, und ist eine der häufigsten Ursachen für einen bug. Wenn Ihr code macht was ganz komisches, immer zu überprüfen, ob Sie initialisiert alle Variablen. Es sollte zum reflex werden, um einen Eintrag in der Initialisierer-Liste für jedes Mitglied-variable, selbst wenn es ruft den default-Konstruktor. Macht die Dinge klar.
Zu C:
Ja. Sehen Sie B für weitere details. Das interessante an der Sache ist, dass, wenn die Methode, die Sie aufrufen, nicht den Zeiger "this" (dieses schließt nicht mit jedem Attribut variable und nicht beim aufrufen einer Methode, die mit einem Attribut, variable), ist Ihre Methode, die garantiert funktioniert. Was passiert beim Aufruf einer Methode auf ein nicht initialisiertes Objekt ist, dass der "this" - Objekt innerhalb der Methode (D. H. alle Attribut-Variablen auch) ist gelegentliches Gedächtnis. Der code der Methode wird ausgeführt, aber die random-Speicher, und dies ist, was fehlschlägt.
Ich hoffe, das klärt die Dinge ein wenig.
Ja
Die Konstruktoren für
myClass_B
gewesen ist, genannt nach dem Aufruf des KonstruktorsmyClass_A()
abgeschlossen ist.In der Regel würden Sie initialisieren die
myClass_B
- Objekt im Konstruktor vonmy_class_A
mit einemMember-Initialisierungsliste.
Wenn ein Objekt erstellt, ist es der Konstruktor wird immer aufgerufen werden, es sei denn, Sie konstruieren ein Objekt, das Sie nicht, rufen Sie eine Methode auf. Dies ist der eigentliche Zweck der Konstruktoren ein Objekt erstellen und initialisieren.
Also, Wenn Sie ein Objekt, es ist nie nicht initialisiert.
Wenn du meinst Zeiger, dann die Zeiger selbst sind nicht Objekte, auf die Sie verweisen können, um ein gültiges oder ungültiges Objekt. Derefencing einen Zeiger(für den Aufruf einer member-Funktion oder was auch immer), die nicht auf ein gültiges Objekt führt Undefiniertes Verhalten.
Antwort auf die zweite Frage Antworten dieser.
A. ja: Konstruktoren der Mitglieder werden aufgerufen, bevor der Konstruktor der übergeordneten Klasse.
B. ja, aber das Ergebnis ist undefiniert Verhalten (= alles passieren kann; auch erscheint, um zu arbeiten.).
Klasse-Mitglieder sind automatisch initialisiert, indem der compiler mit den default-Konstruktor, wenn Sie nichts anderes angeben in Ihrer besitzenden Klasse Konstruktor Initialisierungs-Liste. Ja, der Konstruktor aufgerufen wird.
Testen Sie dies für sich selbst, indem Sie entweder:
Wenn Sie nicht zum aufrufen von Methoden oder der Zugriff auf Mitglieder ein Objekt, das nicht initialisiert oder bereits schon zerstört (beide Szenarien sind möglich engineer) dann haben Sie Undefiniertes Verhalten.
new
zum erstellen einer aktuelle Instanz; zuweisen einer zufälligen Position im Speicher an den Zeiger und dann versuchen, Zugriff auf das "Objekt" - zeigt es auf, mit->
. Für zusätzlichen Spaß, Ingenieur der Inhalt der Position, die Sie zeigen, um in irgendeiner Art und Weise, die Sie wählen, bevor derefing den Zeiger.A. Der Konstruktor für Ihre Klasse myClass_A wird als das moment, das Objekt der Klasse myClass_B instanziiert wird.
B. Sie können Methoden aufrufen unintialized Objekte zum Beispiel
werfen Sie eine Ausnahme.
C. Sie können nie rufen Sie eine Methode, die erfolgreich ohne das Objekt vollständig konstruiert ist.