Problem mit pure virtual



  • Hey, hab da ein Problem mit pure viirtual methoden.

    Folgendes habe ich atm:

    class Grafik {
    public:
    virtual void draw()=0;
    }
    
    class Sprite : public Grafik {
    public:
    virtual void draw()=0;
    }
    
    class MoveSprite : public Sprite {
    public:
    void draw() {
    // Do Sth
    }
    }
    

    Der Sinn soll sein, alle grafische Objekte mittels Grafik->draw(); ansprechen zu können, aber wenn ich das probiere (also ein moveSprite erstelle, als Grafik g speichere und g->draw() ausführe) kriege ich ein SegmentationFault, wobei er nicht einmal das erste std::cout in der MoveSprite->draw() ausführt.

    Kann mir da wer auf die Sprünge helfen?

    mfg



  • Code, wie du das Objekt erstellst und die Funktion aufrufst wäre auch hilfreich.

    Hier sehe ich nur, dass du den Destruktor nicht virtuell machst, was zwar nicht das Problem sein sollte, aber generell gemacht werden sollte.



  • Hmm das Ding ist teil eines ganzen quasi-Frameworks.

    Hier mal das ganze Grafik-Objekt:
    Header:

    class GraficsObject {
    protected:
        int x,y,type;
        SDL_Surface* screen;
        SDL_Rect* rect;
    public:
        GraficsObject(SDL_Surface* screen);
        virtual void draw()=0;
        SDL_Rect* getRect();
        void setPosition(int x, int y);
    
    };
    

    Implementierung:

    GraficsObject::GraficsObject(SDL_Surface* screen) {
            GraficsObject::rect= new SDL_Rect();
            GraficsObject::screen = screen;
        }
    
        void GraficsObject::setPosition(int x, int y) {
            GraficsObject::x=x;
            GraficsObject::y=y;
            GraficsObject::rect->x=x;
            GraficsObject::rect->y=y;
        }
    
        SDL_Rect* GraficsObject::getRect() {
            return GraficsObject::rect;
        }
    

    Sprite Header

    class Sprite : public GraficsObject {
    protected:
        SDL_Surface* texture;
    public:
        Sprite(SDL_Surface* screen);
        virtual void draw()=0;
        void setImage(SDL_Surface* image);
    };
    

    Sprite Implementierung:

    Sprite::Sprite(SDL_Surface* screen) : GraficsObject(screen) {
        }
    
        void Sprite::setImage(SDL_Surface* image) {
            Sprite::texture = image;
        }
    

    MovableSprite Header:

    class MovableSprite : public Sprite {
     public:
         MovableSprite(SDL_Surface* screen);
         void move(Vector2d* velocity);
         void draw();
     };
    

    Implementierung:

    MovableSprite::MovableSprite(SDL_Surface* screen) : Sprite(screen) {
    
        }
    
        void MovableSprite::move(Vector2d* velocity) {
            MovableSprite::x=velocity->getX();
            MovableSprite::y=velocity->getY();
            MovableSprite::rect->x=MovableSprite::x;
            MovableSprite::rect->y=MovableSprite::y;
        }
    
        void MovableSprite::draw() {
            std::cout<<"DEBUG DRAW 1\n"<<std::flush;
            SDL_BlitSurface(MovableSprite::texture,NULL,MovableSprite::screen,MovableSprite::rect);
        }
    

    Erstellt wirds so:

    temp1 = new MovableSprite(RenderingModule::screen);
                    temp1->setImage(imageManager->getBMP("Mario1"));
                    temp1->setPosition(0,0);
                    gObjects->insert(std::make_pair(objectID,temp1));
                    free(temp1);
    

    Und der aufruf erfolgt über einen iterator:

    std::cout<<"DEBUG 6\n"<<std::flush;
            std::map<int,GraficsObject*>::iterator iter;
            std::cout<<"DEBUG 7\n"<<std::flush;
            for(iter = RenderingModule::gObjects->begin(); iter!=RenderingModule::gObjects->end();++iter ) {
                std::cout<<"DEBUG 8\n"<<std::flush;
                std::cout<<"DEBUG DRAWMODULE 8 rect->x = "<<(iter->second->getRect()->x)<<"\n"<<std::flush;
                iter->second->draw();
                std::cout<<"DEBUG 9\n"<<std::flush;
    

    Und da zeigt er mir als letztes das x vom Rect an, dannach kommt der SegFault

    mfg



  • Du fügst also das mit new angelegte Objekt in eine Map ein, löscht es (auch noch mit free!) und greifst dann darauf zu? Das muß ja schief gehen!



  • Nie new mit free mischen. Immer new in Verbindung mit delete verwenden!



  • Ja es war tatsächlich das free, das komische an der Sache war nur, dass die Ausgabe von x immer den richtigen Wert zurückgegeben hat ... Danke euch



  • Das ist nicht komisch, sondern einfach nur Glück und ganz einfach zu erklären. Wenn du den Speicher frei gibst, was du eigentlich nicht tust, wenn du new mit free mischst, dann wird ja nicht gleich der Speicherplatz, auf den gezeigt wurde überschrieben. Sprich die Daten bleiben dort solange liegen, bis ein weiteres new den Speicherplatz neu vergeben hat und du etwas anderes drauf schreibst. Das du new und free nicht mischen sollst hat damit zu tun, dass die Funktionen jeweils aus einem eigenen Speicherpool Adressen zurück geben. In deinem Fall scheint new einfach selber an malloc weiter zu delegieren, weil sonst hätte dein free schon ein Problem verursachen müssen. Vorausgesetzt malloc hatte nicht irgendwann die selbe Adresse zurück gegeben, aber dann kracht es an anderer Stelle.



  • Paul Müller schrieb:

    Das du new und free nicht mischen sollst hat damit zu tun, dass die Funktionen jeweils aus einem eigenen Speicherpool Adressen zurück geben.

    Das ist nicht der einzige Grund. free ruft auch den Destruktor des Objekts nicht nicht auf.



  • manni66 schrieb:

    free ruft auch den Destruktor des Objekts nicht nicht auf.

    Das stimmt, der dtor kann in diesem Fall aber manuell aufgerufen werden, siehe placement-new.



  • Paul Müller schrieb:

    Das stimmt, der dtor kann in diesem Fall aber manuell aufgerufen werden, siehe placement-new.

    Kann er in diesem Fall eben nicht. Weil der Speicher eben mit new angefordert wurde und deshalb auch mit delete freigegeben werden muss.



  • Das war auch so gemeint, da ich auf den anderen Grund von manni66 geantwortet habe. Auch wenn ich den Beisatz raus editiert habe, so steht er noch einmal komplett drüber.


Anmelden zum Antworten