Wie würden Sie den Konstruktor der folgenden Klasse in diesen drei Situationen nennen: Globale Objekte, Arrays von Objekten und Objekte, die in einer anderen Klasse / Struktur enthalten sind?
Die Klasse mit dem Konstruktor (wird in allen drei Beispielen verwendet):
%Vor%Und hier sind meine Versuche, diesen Konstruktor aufzurufen:
Dort versuche ich, den Konstruktor für alle Elemente der Arrays aufzurufen, aber ich würde auch gerne wissen, wie man es für einzelne Elemente aufruft.
Ihr ist der einzige Weg. Auf der anderen Seite versuchen Sie dies zu vermeiden. Es ist besser, Funktionen (oder sogar andere Objekte) als Fabriken zu verwenden. Auf diese Weise können Sie den Zeitpunkt der Erstellung steuern.
Es gibt keine Möglichkeit, dies direkt zu tun. Non-POD-Objekte werden immer standardmäßig erstellt. std::fill
ist oft eine große Hilfe. Vielleicht möchten Sie auch nach Zuweisern und std::uninitialized_fill
suchen.
Verwenden Sie Initialisierungslisten in Ihrem Konstruktor:
%Vor%Statische Member müssen eigentlich außerhalb der Klasse definiert werden:
%Vor%Um einige Missverständnisse über Globals zu korrigieren:
Nicht etwas, aber ich empfehle aber: Also eine einfache Lösung ist es, alle Globals in eine einzige Kompilierungseinheit zu setzen.
Alternativ können Sie die Verwendung statischer Variablen für Funktionen ändern.
Grundsätzlich können Sie eine Funktion haben, die einen Verweis auf das gewünschte globale Objekt zurückgibt (das globale innerhalb der Funktion definiert). Es wird bei der ersten Verwendung erstellt (und in umgekehrter Reihenfolge der Erstellung zerstört).
Die Konrad-Antwort ist in Ordnung, nur eine Erläuterung zu den Arrays .... Es gibt eine Möglichkeit, ein Array von Elementen (keine Zeiger) zu erstellen, und hier folgt:
%Vor%Dieser Ansatz wird hier beschrieben: Ссылка
Für den globalen Fall gibt es keine Möglichkeit zu steuern, wann es aufgerufen wird. Die C ++ - Spezifikation besagt im Wesentlichen, dass sie vor main () aufgerufen wird und irgendwann danach zerstört wird. Abgesehen davon kann der Compiler frei tun, was er will.
Im ersten Array-Fall erstellen Sie ein statisches Array von Foo-Objekten. Standardmäßig wird jeder Wert im Array mit dem Standardkonstruktor von Foo () initialisiert. Es gibt keine Möglichkeit mit einem Raw-C ++ - Array einen bestimmten überladenen Konstruktor zum Aufruf zu zwingen. Sie können ein bisschen Kontrolle ableiten, indem Sie zu einem Vektor anstelle eines Arrays wechseln. Der Vektorkonstruktor hat einen überladenen Konstruktorvektor (size, defaultValue), der erreichen soll, wonach Sie suchen. Aber in diesem Fall müssen Sie vorsichtig sein, denn anstatt Foo (3) aufzurufen, wird es Foo (const Foo & amp; other) nennen, wo andere Foo (3) ist.
Der zweite Array-Fall ist dem ersten Fall sehr ähnlich. Der einzige wirkliche Unterschied ist, wo der Speicher zugewiesen wird (auf dem Heap anstelle des Stapels). Es hat die gleiche Einschränkung hinsichtlich des Aufrufs des Konstruktors.
Der enthaltene Fall ist ein anderes Problem. C ++ hat eine klare Trennung zwischen der Definition eines Feldes innerhalb eines Objekts und der Initialisierung des Feldes. Um dies in C ++ zum Laufen zu bringen, müssen Sie Ihre Balken-Definition in die folgenden ändern:
%Vor%Es scheint den allgemeinen Kern in diesem Thread zu geben, dass Sie Mitglieder eines Arrays nicht anders als den Standardkonstruktor initialisieren können. Eine Antwort erstellt sogar einen anderen Typ, nur um einen anderen Konstruktor aufzurufen. Obwohl Sie können ( wenn das Array nicht als Mitglied einer Klasse ist! ):
%Vor%Der Typ muss jedoch kopierfähig sein: Die angegebenen Elemente werden in die Mitglieder des Arrays kopiert.
Für Arrays als Member in Klassen ist es derzeit am besten, Container zu verwenden:
%Vor% Die von andy.gurin beschriebene placement-new
-Technik ist ebenfalls eine Option. Aber beachten Sie, es wird die Dinge komplizieren. Sie müssen Destruktoren selbst aufrufen. Und wenn ein Konstruktor wirft, während Sie noch das Array aufbauen, dann müssen Sie herausfinden, wo Sie aufgehört haben ... Wenn Sie Arrays in Ihrer Klasse haben wollen und diese initialisieren wollen, verwenden Sie std::vector
. ist eine einfache Wette.
Konstruktion von Arrays von Objekten:
Sie können Ihr ursprüngliches Beispiel mithilfe von Standardparametern ändern.
Derzeit wird nur der Standardkonstruktor unterstützt.
Dies ist etwas, das in der nächsten Version angesprochen wird (weil jeder diese Frage stellt)
C ++ 0X Initialisierungslisten lösen dieses Problem für die Groß- und Kleinschreibung. Siehe diesen Herb Sutter Blogeintrag, wo er sie im Detail beschreibt.
In der Zwischenzeit können Sie das Problem möglicherweise so umgehen:
%Vor% Hier ist die Klasse Foo_3
nur zum Aufruf des Konstruktors Foo
mit dem korrekten Argument vorhanden. Sie könnten es sogar zu einer Vorlage machen:
Auch dies könnte nicht genau das tun, was Sie wollen, aber vielleicht gibt es etwas zum Nachdenken.
(Beachten Sie auch, dass Sie sich in Ihrer Klasse Foo
wirklich die Angewohnheit zunutze machen sollten, Member-Initialisiererlisten anstelle von Zuweisungen im Konstruktor zu verwenden, wie in meinem obigen Beispiel)
Ich denke, es gibt zwei Möglichkeiten, um sicherzustellen, dass Konstruktoren von globalen Klassenobjekten zum Zeitpunkt ihrer "Erstellung" sicher aufgerufen werden:
Deklarieren Sie sie in einem Namespace und machen Sie diesen Namespace global zugänglich.
Machen Sie es zu einem globalen Zeiger auf das Klassenobjekt und weisen Sie ihm ein neues Klassenobjekt in main () zu. Erteilten Code für Konstrukteure anderer globaler Objekte, die auf das Objekt zugreifen, werden davor ausgeführt.
Nur meine zwei Cent.
Tags und Links c++ constructor oop