Mehrere Objekte erstellen in einem Array



  • Danke erstmal für deine Hilfe, leider kommt der Fehler wirklich auf einer Position nach dem Ende des Codes. Ich hab eine Leerzeile zur besseren übersicht beim Übertragen entfernt, bei Ausführung waren es also 38 Zeilen.
    Eigentlich würde ich auch eher ein normales Array für den Zweck bevorzugen statt dem vector, da ich die objects eh nur einmalig initialisieren und danach nicht mehr ändern muss.



  • @loolery sagte in Mehrere Objekte erstellen in einem Array:

    da ich die objects eh nur einmalig initialisieren und danach nicht mehr ändern muss.

    struct foo_t { char const * const foo; unsigned id; };
    
    // ...
    
    foo_t foo[] = {
        { "Mike", 0 },
        { "Ann", 1 },
        { "Han", 2 },
        { "Susan", 3 },
        { "Knut-Hansen", 4 }
    };
    

    fertig, aber eigentlich:

    char const * const foo[] = { "Mike", "Ann", "Han", "Susan", "Knut-Hansen" };
    

  • Mod

    @loolery sagte in Mehrere Objekte erstellen in einem Array:

    Danke erstmal für deine Hilfe, leider kommt der Fehler wirklich auf einer Position nach dem Ende des Codes.

    Das kommt dir nicht irgendwie komisch vor? Offensichtlich übersetzt du einen ganz anderen Code als du denkst.



  • @Swordfish sagte in Mehrere Objekte erstellen in einem Array:

    @loolery sagte in Mehrere Objekte erstellen in einem Array:

    da ich die objects eh nur einmalig initialisieren und danach nicht mehr ändern muss.

    struct foo_t { char const * const foo; unsigned id; };
    
    // ...
    
    foo_t foo[] = {
        { "Mike", 0 },
        { "Ann", 1 },
        { "Han", 2 },
        { "Susan", 3 },
        { "Knut-Hansen", 4 }
    };
    

    fertig, aber eigentlich:

    char const * const foo[] = { "Mike", "Ann", "Han", "Susan", "Knut-Hansen" };
    

    Danke für deine Mühe, aber das hilft mir leider beim eigentlichen Problem nicht weiter. Mir geht's allein um das Speichern mehrerer Objekte per Schleife in ein Array, die Liste und alles andere drum herum diente nur dem besseren Verständnis hier.

    Ich verstehe bisher leider nicht warum es in C++ so simple ist ein Array einzeln mit Objekten aus einer Klasse zu füttern, aber sobald man das mit einer Schleife tun möchte nicht mehr auf dem selben Weg möglich ist. 🤷


  • Mod

    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.


  • Mod

    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 Klasse test 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 von ID und Name hätte dann deiner Meinung nach das Element foo[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()


  • Mod

    @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 mit 0 Byte Werten belegt. Und dann kann man nachträglich den einzelnen Array-Werten mittels new(...) neue Werte zuordnen.
    In C++ muß man aber dafür dann explizit Zeiger (bzw. Shared-Pointer) verwenden.


  • Mod

    Wertetypen und Zeiger werden in C++ auch automatisch nullinitialisiert, wenn man nix sagt (was nicht einmal unbedingt null/0 heißt). Aber das test ist halt kein solcher Typ. Da ist in Java das Array[test] eben nur ein verkapptes Array[*test]. Auch Java könnte nicht zaubern, und würde genauso meckern, wenn man ein new(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] oder std::unique_ptr<test> foo[5] deklariert (5 mögliche foos), sondern test 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.


Anmelden zum Antworten