Liste, abstrakte Klasse und Iteration



  • mahlzeit,
    mein Problem besteht in der Erstellung von einer Liste (STL), die Objekte einer abstrakten KLasse enthält, durch die ich iterieren will, um dabei eine Methode aufzurufen.
    GrafischeObjekte sind dabei zum Beispiel Kreise und Linien oder Quadrate; die Methode wäre hier im Beispiel draw():

    class PaintProgram
    {
    	private:
    		list<GraphicalObject*> graphicalObjectList;
    	public:
    		void addGraphicalObject( GraphicalObject& go )
    		{
    			graphicalObjectList.push_back( &go );
    		}
    
    		void drawObjects()
    		{
    			list<GraphicalObject*>::iterator iter;
    			iter = graphicalObjectList.begin();
    			while(iter != graphicalObjectList.end())
    				iter->draw();
    		}
    
    };
    

    Nun hapert es aber am Aufruf der draw() Methode...
    Was mache ich da falsch, ist es ein konzeptionelles Problem oder stimmen meine Zeigerkonstruktion einfach nicht?!
    MfG tazz



  • Ich tippe mal auf ein konzeptionelles Problem - du hast vergessen, den list-Iterator in der Schleife zu inkrementieren, darum wird die drawObjects() das erste Objekt deiner Liste in einer Endlosschleife immer wieder ausgeben.

    (wenn das nicht das Problem war: Wie äußert sich das "nun hapert es am Aufruf der draw() Methode"?)



  • Ich würde spekulieren, dass ein Zeiger generell keine Methoden hat, aber das Spekulieren habe ich mir abgewöhnt.

    Was ist eigentlich so schwer daran, eine ordentliche Fehlerbeschreibung zu posten?



  • hi,
    ja ich geb zu, "mit hapert es ein bisschen" kann wohl kaum jemand was anfangen 😉
    Dass der Iterator sich nicht von allein inkrementiert ist mir noch gar nicht aufgefallen, weil ich es leider auch noch nicht geschafft habe das Programm fehlerfrei zu übersetzen.
    Compiler-Fehler:

    error: request for member `draw' in `(&iter)->std::_List_iterator<_Tp>::operator-> [with _Tp = GraphicalObject]()', which is of non-class type `GraphicalObject*'

    Wer weiß was er mir damit sagen will...



  • Hallo,

    ich gebe meine vorpostern erst mal recht.

    Aufruf:

    (*iter)->draw();
    

    Dann noch ein Hinweis.. Wie benutzt du die methode ?

    void addGraphicalObject( gaphicalObject& go )
    

    Wenn du ihr eine stack Varivable übergibst wird es gefährlich.



  • Aha, für eine ausführliche Fehlermeldung gibt's auch ne ausführliche Hilfestellung 😉

    Genau wie ich vermutet habe:
    Der Aufruf iter->draw() bedeutet nichts anderes als (*iter).draw(). Und da Du in Deinem Vector Zeiger speicherst, ist (*iter) ein Zeiger. Ein Zeiger hat aber keine Methode draw(), sondern das worauf er zeigt hat eine Methode draw().
    Korrekt wäre also (**iter).draw() oder (üblicher) (*iter)->draw(). Denn das Dereferenzieren des Iterators liefert Dir ein Zeiger-auf-GraphicalObject, und das Dereferenzieren dieses Zeigers liefert Dir ein GraphicalObject, und dieses widerum hat eine Methode draw().



  • mahlzeit,
    tschuldigung, dass ich mich nicht mehr gemeldet habe - der erste Teil meines Wochendes war ein wenig stressig - bestand hauptsächlich aus geburtstagsparty und wohnungsumräumungen...
    naja ist auch egal!
    ich danke erstmal allen, es lag in der tat nur an diesen zwei netten klammer 😉
    @templäd:
    ich habe meine methode nochmal leicht geändert, weil ich von vornherein eigtl nur zeiger auf diese objekte in meiner liste speichern wollte:

    void addGraphicalObject( GraphicalObject* go )
    {
    	graphicalObjectList.push_back( go );
    }
    

    also mit new erzeugen und dann übergeben!
    kannst du, oder jemand anders, mir trotzdem erklären, wo das Problem bestände, wenn ich Stackvariablen übergebe?!
    thx schon mal wieder im Voraus...
    noch ein schönes Wochenende



  • Kurz gefasst: Ein Zeiger kann später nicht mehr überprüfen, ob er auf ein gültiges Objekt zeigt. Das heißt, wenn du so etwas hast:

    void doSomething()
    {
      Circle ob;
      ...
      addGraphicalObject(ob);
    }// <-
    

    dann wird an der Position des Pfeils dein Objekt vernichtet (das gehört zu den Aufräumarbeiten am Ende einer Funktion) und der Zeiger, den du in der Objektliste gespeichert hast, zeigt auf fremde Daten. Und nur mit sehr viel Glück steht beim nächsten Aufruf von drawObjects() an dieser Adresse noch etwas, was als Grafik-Objekt erkennbar ist.


Anmelden zum Antworten