Mit Iterator auf Member-Funktion zugreifen



  • fr33g schrieb:

    Soll ich das ganze dann so lösen:

    void Inventar::itemLoeschen()
    {
        for( theIt = items.begin(); theIt != items.end(); ++theIt )
        {
            if( ( *theIt )->getVerfuegbarkeit() == 0 )
            {
                items.erase( theIt );
                cout << "\n" << ( *theIt )->getName() << " wurde gelöscht\n";
            }
        }
    }
    

    Nein, das macht deinen Iterator ungültig. Sobald erase() zum Aufrufer zurückkehrt, ist jeder Zugriff auf folgende Iteratoren und insbesondere theIt selbst undefiniert.

    Eine Lösung könnte so aussehen:

    void Inventar::itemLoeschen()
    {
        for( theIt = items.begin(); theIt != items.end(); /* nichts */)
        {
            if( ( *theIt )->getVerfuegbarkeit() == 0 )
                theIt = items.erase( theIt );
            else
                ++theIt;
        }
    }
    

    Für genau diesen Zweck existiert übrigens der STL-Algorithmus std::remove_if() .

    bool itemNichtVerfuegbar(const Item* item)
    {
        return (item->getVerfuegbarkeit() == 0);
    }
    
    void Inventar::itemLoeschen()
    {
        std::remove_if(items.begin(), items.end(), &itemNichtVerfuegbar);
    }
    

    Wichtig: Ich bin hier von nicht-besitzenden Zeigern ausgegangen.

    Falls du die Zeiger mit new anforderst, musst du sie mit delete freigeben. Dadurch wird die Sache unnötigerweise massiv komplizierter und fehleranfälliger, vermeide manuelle Speicherverwaltung wo möglich. Falls der Container die Gegenstände tatsächlich besitzen sollte: Gibt es einen Grund, weshalb du std::vector<Item*> und nicht std::vector<Item> benutzt? Bei der zweiten Variante brauchst du dich nämlich nicht um Speicher zu kümmern.

    Übrigens, aber das ist eher Geschmackssache: Ich persönlich würde mich für eine Sprache entscheiden. Also "RemoveItem" oder "LoescheGegenstand" (wobei ich zu englisch tendiere). Finde ich einfach konsistenter.



  • Erst mal Danke für die Antworten,
    zu der Frage warum ich zeiger auf Items im Vektor speichere.
    Item ist die Basisklasse, diese hat nun wieder 3 Kindklassen, welche wieder eigene Kindklasse haben. Ich dachte wenn ich jetzt im Vektor nur Items speichere, dann kann ich auch nur Items und nich die Spezialisierung, sprich ich müsste für jede Klasse nen eigenen Vektor erstellen.
    Oder bin ich da der Annahme falsche und das funktioniert als wie ich es mit einem Zeiger auf Item löse?



  • Es ist schon richtig das du Zeiger verwendest in diesem Fall, aber eventuell solltest du dabei auf einen Smart Pointer zurückgreifen um memory leaks zu vermeiden. boost::shared_ptr<> z.B.



  • Ok, habe schon öfters was von Smart Pointer gehört, jedoch weiß ich nicht was sie sind und wie man sie benutzt.
    Aber werde mich da jetzt mal im Internet schlau machen und sie gegeben falls nutzen.
    Weiß jetzt immerhin dass mein Ansatz das mit Zeigern zu lösen richtig war=)

    Leute, ich bekomme die Boost Bibliothek irgendwie nicht installiert.
    Hab schon reichlich gegoogelt und auch getStarted bei boost durchgelesen.

    Ich soll doch die build.bat ausführen, und dannach die daraus resultierende exe
    Jedoch komm ich soweit gar nicht, bekomme immer beim ausführen der build.bat fehler:

    http://img7.imageshack.us/img7/8372/boostfehler.png

    Hoffe ihr könnt mir helfen.



  • "Boost installieren" ist in den meisten Fällen überflüssig. Du extrahierst die Header die du brauchst und bindest die in dein Objekt ein. Fertig.

    Sachen wie boost::signals oder boost::filesystem brauchen hingegen eine kompilierte Bibliothek. Aber das interessiert dich im Moment noch nicht.
    shared_ptr kommt ohne lib zurecht.



  • Wie meinst du ich extrahiere die Header-Datei???
    Und wo muss ich sie hinextrahieren, bzw kopieren?
    In das mingw verzeichnis?



  • Wohin spielt keine Rolle, du musst den Pfad nur in deinen Compiler Settings in den Include Suchpfad aufnehmen.



  • Boost kommt doch in einem riesigen fetten .tar.bz2 (oder .zip, weiß grad nicht ob die für Windows was eigenes schnüren...)
    Das entpacken und in das erstellte Verzeichnis reingehen. Dort das Verzeichnis "boost" in deinen Projekttree kopieren. Danach kannst du alles rausschmeißen was du nicht brauchst. Schau in den Header "boost/shared_ptr.hpp", was includiert wird. So kannst du die weiterhangeln. Übrig bleiben wird eine Hand voll Headerdateien. Die brauchen nicht wirklich viel Platz, und wenn du dein Projekt auslieferst muss sich derjenige nicht auch gleich boost zum Kompilieren zulegen...
    Alternativ boost entzippen und das Verzeichnis bei den Include-Pfaden mit angeben.
    Siehe auch hier
    http://www.boost.org/doc/libs/1_42_0/more/getting_started/windows.html#header-only-libraries



  • Wenn man nur besitzende Zeiger in Containern speichern will, sind Boosts Pointer-Container weitaus sinnvoller als Smart-Pointer. Die Benutzung ist intuitiver, weil die Schnittstelle weitgehend zur STL kompatibel ist und man nicht zusätzlich dereferenzieren muss. Nullzeiger sind standardmässig verboten. Ausserdem sind die Pointer-Container exceptionsicher und haben keinen unnötigen Overhead für eine Shared-Semantik.

    Kurz: Sie sind für den Fall hier geradezu ideal.

    boost::ptr_vector<Item> items;
    items.push_back(new SpecialItem); // SpecialItem erbt von Item
    
    items[0].DoSomething(); // operator. und nicht operator->
    
    boost::ptr_vector<Item>::iterator itr = items.begin();
    itr->DoSomething(); // itr->DoSomething() und nicht (*itr)->DoSomething()
    


  • Hey Leute,
    vielen Dank für die vielen Infos und Tipps.
    Werd mich jetzt mal bissel durch die Boost Doku durchkämpfen und sie dann in meinem Projekt einsetzen;-)
    Danke schonmal=)



  • fr33g schrieb:

    Hey Leute,
    vielen Dank für die vielen Infos und Tipps.
    Werd mich jetzt mal bissel durch die Boost Doku durchkämpfen und sie dann in meinem Projekt einsetzen;-)
    Danke schonmal=)

    Ich freu´ mich schon auf die Aha!, Oha! und Nein, sowas! Effekte 😉


Anmelden zum Antworten