Liste von Objekten



  • Ja bei statischen Objekten ist mir das Kopieren klar. Aber ich meinte, wenn ich jetzt z.B. um bei dem Beispiel von Oben mit den Schülern bleibe. Wenn ich da ein neues Objekt erstelle, was dann in die Liste soll. Wie geht das als Kopie? Ich habe doch darauf nur einen Zeiger. Und mit der Liste/Vektor Diskussion, weiß ich jetzt gar nciht mehr, was ich am einfachsten für kleine Projekte nehme. Ich möchte wie gesagt einfach Objekte hinzufügen und löschen allerdings nciht nur das erste bzw. das letzte, sonder ein beliebiges. Und Operationen mit allen Objekten durchführen.



  • Ach ja ich würde jetzt in der Klasse Schule eine Methode machen, die einen neuen Schüler erstellen kann. Also So was in der Art, wie es von L33TF4N gepostet wurde. Ich weiß eben nur nicht, wie man das per Kopie machen will.



  • Leon222 schrieb:

    Ja bei statischen Objekten ist mir das Kopieren klar.

    In C++ gibt es drei Speicherklassen: statisch, automatisch und "dynamisch" (Freispeicher). Mit dem Kopieren hat das aber nichts zu tun.

    Leon222 schrieb:

    Aber ich meinte, wenn ich jetzt z.B. um bei dem Beispiel von Oben mit den Schülern bleibe. Wenn ich da ein neues Objekt erstelle, was dann in die Liste soll. Wie geht das als Kopie? Ich habe doch darauf nur einen Zeiger.

    Dann hast Du schon etwas falsch gemacht, wenn Du "doch darauf nur einen Zeiger" hast.

    #include <string>
    #include <list>
    #include <iostream>
    
    struct dings
    {
      string bums;
    
      dings() {} // default constructor
    
      explicit dings(string b) : bums(b) {}
    };
    
    template<class Iter>
    void dings_sequenz_anzeigen(Iter beg, Iter end)
    {
      while (beg!=end) {
        std::cout << ' ' << beg->bums;
        ++beg;
      }
      std::cout << '\n';
    }
    
    int main()
    {
      list<dings> l;
    
      l.push_back( dings("123") );
    
      l.push_back( dings() );
      l.back().bums = "234";
    
      dings d ("999");
      l.push_back(d);
    
      d.bums = "9191";
      l.push_back(d);
    
      dings_sequenz_anzeigen(l.begin(),l.end());
    }
    


  • Naja ich meinte dynamisch mit new erzeugt Objekte.

    void addSchueler(int id)
        {
            m_schueler.push_back(new Schueler(id));
        }
    

    Wie sollte man das mit einer Kopie realisieren?



  • Leon222 schrieb:

    Naja ich meinte dynamisch mit new erzeugt Objekte.

    void addSchueler(int id)
     {
         m_schueler.push_back(new Schueler(id)); 
     }
    

    Wie sollte man das mit einer Kopie realisieren?

    Ich verstehe nicht, was Du meinst, verstehe Dein Problem nicht. Ich weiß nicht, was Du wissen willst.



  • SeppJ schrieb:

    Im übrigen: Du brauchst keine Zeiger. Hast du früher zufällig mal Java programmiert? In C++ macht man das was du da zeigst eigentlich mit Kopien. Die dynamische Verwaltung ist genau das, wozu die Container gut sind. Du musst gar nicht mehr selbst mit new/delete arbeiten.

    Das meinte ich. Ich will eben zur Laufzeit Objekte anlegen. Eben z.B. mit einer methode neuerSchueler. Aber wie bitte soll das ohne new mit Kopien gehen?



  • Leon222 schrieb:

    Ich will eben zur Laufzeit Objekte anlegen. Eben z.B. mit einer methode neuerSchueler. Aber wie bitte soll das ohne new mit Kopien gehen?

    Du siehst wohl den Wald vor lauter Bäumen nicht. Guck Dir nochmal ganz genau mein letztes Codebeispiel an.



  • Leon222 schrieb:

    Ich will eben zur Laufzeit Objekte anlegen. Eben z.B. mit einer methode neuerSchueler. Aber wie bitte soll das ohne new mit Kopien gehen?

    Du siehst wohl den Wald vor lauter Bäumen nicht. Guck Dir nochmal ganz genau mein letztes Codebeispiel an.



  • Nein so richtig sehe ich das noch nciht. heißt das ich kann einfach schreiben:

    void addSchueler(int id)
        {
            m_schueler.push_back(Schueler(id));
        }
    


  • Leon222 schrieb:

    Nein so richtig sehe ich das noch nciht. heißt das ich kann einfach schreiben:

    void addSchueler(int id)
        {
            m_schueler.push_back(Schueler(id));
        }
    

    Genau! Dann muss m_schueler aber als std::list<Schueler> deklariert sein, bei der Zeigervariante mit new wäre es ja std::list<Schueler*> .



  • Gut das war mir bisher nciht bekannt, dass das ohne new geht. Hat es denn einen Vorteil, dass ganze ohne Zeiger zu realisieren? Und ist nun List oder Vektor besser für mein Vorhaben. Was ich jetzt so gelesen habe würde ich List den Vorzug geben.



  • Leon222 schrieb:

    Gut das war mir bisher nciht bekannt, dass das ohne new geht. Hat es denn einen Vorteil, dass ganze ohne Zeiger zu realisieren?

    Der Vorteil besteht darin, dass du keine manuelle Speicherverwaltung mehr hast.

    Leon222 schrieb:

    Und ist nun List oder Vektor besser für mein Vorhaben. Was ich jetzt so gelesen habe würde ich List den Vorzug geben.

    Dazu wurde dir schon zwei Mal eine Antwort gegeben (SeppJ und drakon).



  • Naja mir wurden halt mehrmals die Vor und Nachteile der beiden Klassen genannt. Ich wollte nur nochmal wissen, ob ich das jetzt richtig interpretiert habe, und List für mich das beste ist.



  • Wie erwähnt ist das schwer zu sagen, ohne genau zu wissen, welche Operationen wie häufig vorkommen und ob besondere Anforderungen (z.B. Gültigkeit der Iteratoren) gestellt werden. Nimm fürs Erste einmal std::vector , für die meisten Fälle ist er am geeignetsten.



  • Also ich wollte erst einmal ein kleines Testprojekt machen wo ich wie schon geschrieben Objekte in die Liste einfüge, und anhand der id wieder lösche. Ansonsten werden die Objekte nur für eine Methode gebraucht und dort soll eine Variable aller Objekte aufsummiert werden. Also z.B. den Durchschnitt aller Gesamtnoten der Schüler berechnen. Da sollte bald die Liste besser sein.

    Worüber ich mir jetzt noch Gedanken mache ist die Nummerierung der Objekte. Ich wollte das ja erst mit new machen. Da hätte ich die Nummerierung der Klasse Schüler überlassen. Dort 2 static Variablen letzte id und anzahl. und eine normale Variable id. Beim Erzeugen eines neuen Objektes wird id der wert ++letzteid zugewiesen. Aber das klappt ja jetzt durch das kopieren nicht mehr, oder?



  • Kannst du als Nummer nicht den Index des Containers (in dem Fall std::vector ) verwenden? Oder wofür brauchst du die Nummerierung genau?



  • Also die Nummerierung des Vektor ist vlt zwecks löschen nciht so gut, oder? Also die Nummerierung benötige ich um das Objekt zu löschen. Also z.B. Schüler mit Nummer 14546 löschen.



  • Entweder du gibst der Schüler-Klasse diese Eigenschaft und führst im Container eine lineare Suche durch, oder du bildest Schlüssel-Wert-Paare mit Nummern als Schlüsseln und Schülern als Werten. Dazu kannst du std::map verwenden.


  • Administrator

    Klingt mir danach, dass du eine std::map benötigst.

    Oder falls du Boost bereits verwendest und die ID nicht doppelt speichern willst (also als Key und im Objekt selber), dann gäbe es Boost.MultiIndex:

    class pupil
    {
    private:
      int id_;
      // usw.
    
    public:
      int get_id() const { return id_; }
      // usw.
    };
    
    // ...
    
    typedef boost::multi_index::multi_index_container
    <
      pupil,
      boost::multi_index::indexed_by
      <
        boost::multi_index::const_mem_fun<pupil, int, &pupil::get_id>
      >
    > pupil_set;
    
    // ...
    

    multi_index_container braucht aber etwas Zeit, bis man das Ding schlucken kann 🙂

    Grüssli



  • Also Map wäre ich mir anschauen, oder halt dem Schüler die Eigenschaft id geben. Dann muss sich aber das Hauptprogramm darum kümmern, dass es keine Doppelten Nummern gibt, oder?

    Wie kann ich denn eigentlich verhindern, dass Im Hauptprogramm ein Schüler erstellt wird. Denn das soll nur über die Klasse Schule möglich sein. Reicht es da den Konstruktor private zu machen?


Anmelden zum Antworten