Mehrere Objekte erstellen in einem Array
-
Hast du meine Antwort gelesen? Es ist super-simpel, einfacher noch als dein jetziger Code. Du kommst bloß mit deiner Entwicklungsumgebung nicht zurecht und übersetzt wer weiß was, was nicht dein Code ist.
vector<test> objTest; ... objTest.push_back(test(i, cname));
-
@SeppJ sry, ja hat ich gelesen und funktioniert auch, danke.
Ich versteh halt trotzdem nicht wieso es mit dem stdArray ohne weitere includes nicht geht und ich auf Vector ausweichen muss um diese simple Sache in einer Schleife zu bewerkstelligen.
-
Weil ein statisches Array nie "leer" sein kann, es hat ja schließlich genau seine Größe. Ein Array mit 5 Elementen hat immer 5 Elemente. Vom Anfang seiner Lebensdauer bis zum Ende. Und irgendwo müssen die Elemente, die da ganz am Anfang beim Erstellen drin sind, ja herkommen. Nun kann man deine Klasse
test
aber nicht einfach so aus dem Nichts erzeugen (siehe meine erste Antwort, die alles komplett erklärt hatte…), denn sie hat schließlich zwei Argumente. Also musst du beim Erstellen eines Arrays der Klassetest
mit 5 Elementen auch diese 5 Elemente (oder die Argumente dafür) angeben. Das geht dann auch problemlos, wenn du das so machst! Aber irgendwie später Sachen in das Array einfügen geht halt nicht, denn das ist ja gerade der Unterschied zwischen Vector und Array, dass das bei dem einen geht und bei dem anderen nicht.Oder anders gesagt: Wenn das so gehen würde, wie du es vor hast, man also einfach so
test foo[5]; # oder besser: std::array<test, 5> foo;
schreiben könnte, ohne die 5
test
-Elemente anzugeben: Was für Werte vonID
undName
hätte dann deiner Meinung nach das Elementfoo[2]
?
-
@SeppJ Andere Sprachen bekommen das ja sonst hin den Speicher beim laden der Array direkt zu reservieren für die spätere Belegung, davon bin ich bisher wohl einfach zu verwöhnt gewesen. Aber danke für deine doppelte und ausführliche Erklärung.
-
@loolery sagte in Mehrere Objekte erstellen in einem Array:
@SeppJ Andere Sprachen bekommen das ja sonst hin den Speicher beim laden der Array direkt zu reservieren für die spätere Belegung, davon bin ich bisher wohl einfach zu verwöhnt gewesen. Aber danke für deine doppelte und ausführliche Erklärung.
Welche denn? Es geht hier ja nicht um Reservierung von Speicher, sondern um das Erzeugen von Objekten. Ein
test foo[5]
erzeugt 5 Test-Objekte, nicht 5 (möglicherweise auf nullptr gesetzte) Pointer auf Objekte. C++ arbeitet direkt mit Objekten, nicht implizit mit Pointern/Referenzen, außer du nutzt diese explizit.Wenn du nur Speicher reservieren willst:
vector.reserve()
-
@loolery sagte in Mehrere Objekte erstellen in einem Array:
@SeppJ Andere Sprachen bekommen das ja sonst hin den Speicher beim laden der Array direkt zu reservieren für die spätere Belegung, davon bin ich bisher wohl einfach zu verwöhnt gewesen. Aber danke für deine doppelte und ausführliche Erklärung.
Nein, solche Sprachen gibt es nicht. Du verstehst das Problem nicht, wenn du denkst, solche Sprachen könnte es geben. Es ist ein Logikfehler in deinem Programm (oder in deinem Verständnis). Das hat mit egal welcher Sprache nichts zu tun, denn Logik ist in jeder Sprache gleich, und somit auch Fehler in der Logik.
Du kannst nicht Wahrhaft behaupten "Ich habe einen Korb mit 5 Äpfeln" ohne dass du 5 Äpfel in dem Korb hast. Egal ob auf Deutsch, C++, oder jeder anderen Sprache. "Ich habe einen Korb mit 5 Äpfeln" ist nicht das gleiche wie "Ich habe einen Korb mit Platz für 5 Äpfel". Letzteres kann auch wahr sein, ohne dass 5 Äpfel im Korb sind. Sowohl auf Deutsch, C++, oder jeder anderen Sprache. Ein statisches
array<Apfel, 5>
ist aber ein Korb in dem 5 Äpfel drin sind, nicht bloß ein Korb in dem Platz für 5 Äpfel ist. Wenn du so einen Korb mit 5 Äpfeln drin erstellst, dann müssen die 5 Äpfel irgendwo herkommen, ansonsten ist es kein Korb mit 5 Äpfeln drin.
-
Doch, Sprachen wie Java oder C#. Dort wird dann ein Array bei Referenztypen mit
null
bzw. in C# bei Wertetypen mit0
Byte Werten belegt. Und dann kann man nachträglich den einzelnen Array-Werten mittelsnew(...)
neue Werte zuordnen.
In C++ muß man aber dafür dann explizit Zeiger (bzw. Shared-Pointer) verwenden.
-
Wertetypen und Zeiger werden in C++ auch automatisch nullinitialisiert, wenn man nix sagt (was nicht einmal unbedingt
null
/0
heißt). Aber dastest
ist halt kein solcher Typ. Da ist in Java dasArray[test]
eben nur ein verkapptesArray[*test]
. Auch Java könnte nicht zaubern, und würde genauso meckern, wenn man einnew(test)
ohne Argumente macht.
-
@Th69 sagte in Mehrere Objekte erstellen in einem Array:
Doch, Sprachen wie Java oder C#. Dort wird dann ein Array bei Referenztypen ...
Ich habe das wichtige Wort mal markiert. Das ist aber doch hier genau der Unterschied! Es sind hier eben keine
test *foo[5]
oderstd::unique_ptr<test> foo[5]
deklariert (5 mögliche foos), sonderntest foo[5]
. Das sind 5 explizit verlangte foos. In C++ sind Klassen nicht automatisch Referenztypen. Wenn man dann sagt "aber mit Referenztypen geht das in Sprache XY", dann ist das eben nicht das gleiche.
-
Mal ganz einfaches Beispiel in vbsript, wie andere Sprachen das lösen, in C#, Java oder Basic überall so ähnlich auch möglich:
Class testklasse private myid Public Default Function Init(i) myid = i Set Init = Me End Function Public Property Let ID(byVal value) myid = value End Property Public Property Get ID ID = myid End Property End Class Dim objTest(4), ausgabe For i=0 To 4 'ReDim Preserve objTest(i) <- optional in der schleife auch erst reservierbar Set objTest(i) = (New testklasse)(i) Next For r=0 To UBound(objTest) ausgabe = ausgabe & " - " & r Next MsgBox(ausgabe)
Für mich als nicht Kernel-Treiber Hardcore coder ist es so zumindest deutlich angenehmer zu schreiben.
-
Das ist aber was anderes, als du in C++ programmiert hast. In deinem C++ Quelltext hast du explizit gesagt, dass du deine Objekte ausschließlich über einen Konstruktor mit 2 Parametern erzeugen möchtest. Dann darfst du dich also auch nicht beschweren, dass die Konstruktion sperrig ist, das hast du selbst so vorgegeben.
Du kannst natürlich deine Objekte mit ungültigen Werten default-konstruieren:
#include <string> class Test { int ID_ = -1; // Annahme: -1 ist eine ungültige ID std::string Name_; public: Test() = default; // Default Konstruktor erlauben Test( int id, std::string const& name ) : ID_( id ), Name_( name ) { } ... }
Damit kannst du auch "ungültige" Objekte erzeugen, aber dann stellt sich die Frage, warum du ungültige Objekte erzeugst und in einem Array/std::array ablegst, statt einen std::vector zu pflegen, der nur gültige Objekte enthält.
-
Das hat man doch schon versucht, Dir zu erklären ...
Das kannst Du in C++ ähnlich machen, allerdings hast Du dann eben kein Array von Objekten, sondern ein Array von Zeigern/Referenzen auf Objekte.
In Deinem Beispiel werden die Objekte erst in der Schleife erstellt (Zeile 19).Wenn Du in C++ ein Array mit:
Klasse array[5];
definierst, dann werden an der Stelle 5 Objekte vom Typ Klasse erstellt.
Dein Beispiel sähe in C++ etwa so aus:Klasse * array[5];
Dann hast Du ein Array, das nicht Objekte enthält, sondern Zeiger auf Objekte, und diese Zeiger kannst Du dann später auf Objekte zeigen lassen, die Du dann zB in einer Schleife erstellst ...
-
@DocShoe Das der Konstruktor nur 1 Parameter erfordert war gerade rein meiner Faulheit geschuldet, das gleiche mit 2 oder 20 Parametern zu machen ist kein großes Hexenwerk in vbs.
-
@loolery sagte in Mehrere Objekte erstellen in einem Array:
@DocShoe Das der Konstruktor nur 1 Parameter erfordert war gerade rein meiner Faulheit geschuldet, das gleiche mit 2 oder 20 Parametern zu machen ist kein großes Hexenwerk in vbs.
Das ist nicht das, was ich meinte. Du kannst in C++ steuern, wie Objekte erzeugt werden. Wenn du alle Konstruktoren bis auf einen deaktivierst, dann darfst du dich nicht beschweren, dass du Objekte nicht frei Schnauze konstruieren kannst, sondern auf diesen einen Konstruktor beschränkt bist.
-
@Belli sagte in Mehrere Objekte erstellen in einem Array:
Das kannst Du in C++ ähnlich machen, allerdings hast Du dann eben kein Array von Objekten, sondern ein Array von Zeigern/Referenzen auf Objekte.
Oder man nutzt std::optional.