Dynamisches Objekt mit Argumenten erzeugen - Immer noch Fehler (Upd. Seite 2)



  • Ich bekomm einen Speicherfehler.

    std::vector<CAnimation> itsAnimation(5, CAnimation(20,20));
    

    ersetzt

    itsAnimation = new CAnimation(20, 20)[5];
    

    sozusagen ? Oder hab ich was übersehen?

    MfG

    Edit: Oder hab ich nur einen Vektor erstellt für meine Aufgabe?



  • Du kannst einen vector nicht wie ein Array behandeln. Ansonsten kann man hier ohne Code nicht viel sagen.



  • Ich möchte bzw. muss mit

    itsAnimation[0].addFrame();
    

    usw. weiterarbeiten.

    MfG



  • Saiyaman schrieb:

    Ich möchte bzw. muss mit

    itsAnimation[0].addFrame();
    

    usw. weiterarbeiten.

    MfG

    Das sollte funktionieren, wenn CAnimation::addFrame() existiert.



  • void CGuy::addAnimation(int width, int height)
    {
    	if (itsAnimationCount == 0)
    	{
    		std::vector<CAnimation> itsAnimation(1, CAnimation(width, height));
    		//itsAnimation = new (CAnimation(width, height))[1];
    		itsAnimationCount++;
    	}
    }
    
    void CGuy::addFrame(int aniIndex)
    {
    	// Abbruchbedingungen
    	if ((aniIndex < 0) || (aniIndex >= itsAnimationCount))
    		return;
    
    	itsAnimation[aniIndex].addFrame();
    }
    
    void CAnimation::addFrame()
    {
    	if (itsFrameCount == 0)
    	{
    		itsFrame = new BITMAP*[1];
    		itsFrame[0] = create_bitmap(itsWidth, itsHeight);
    		clear_to_color(itsFrame[0], COLOR_WHITE);
    		itsFrameCount++;
    	}
    }
    
    CGuy keen;
    keen.addAnimation(50, 50);
    keen.addFrame(0); // hier tritt ein Fehler auf
    

    Es sieht so aus, alsob noch _KEIN_ Speicher für itsAnimation[0] reserviert wurde. Das scheint die std-Zeile nicht zu machen.

    MfG



  • Du solltest dir mal in deinem Buch das Kapitel über std::vector durchlesen. Es ist das was man anstatt Arrays benutzen sollte. Es dient nicht dazu ein Array zu initialisieren.

    void CGuy::addAnimation(int width, int height)
    {
        if (itsAnimationCount == 0)
        {
            std::vector<CAnimation> itsAnimation(1, CAnimation(width, height));
            //itsAnimation = new (CAnimation(width, height))[1];
            itsAnimationCount++;
        }
    }
    

    Hier wird ein vector erzeugt und auch direkt wieder gelöscht, wenn der Scope verlassen wird.

    Eigentlich ist es so gedacht: CGuy hat einen Datenmember std::vector<CAnimation> itsAnimation;
    Dann sieht addAnimation(int w, int h) so aus:

    void CGuy::addAnimation(int width, int height)
    {
       itsAnimation.push_back(CAnimation(width, heigth));
    }
    


  • Geht jetzt. Danke. Vektoren sind echt cool. 🙂

    itsAnimation.clear();
    

    gibt den ganzen Speicher wieder frei oder?

    MfG



  • Ja, dies muss man aber nur dann machen, wenn man den vector danach erneut füllen möchte. Ansonsten wird der Speicher durch den Destruktor des Vektors freigegeben.



  • Also mit einer Animation klappt das jetzt. Aber sobald ich 2 Animationen erstelle, kommt beim Beenden (!) des Programms folgender "Fehler":

    Unbehandelte Ausnahme bei 0x77f65a58 in keen.exe: Benutzerhaltepunkt.

    Zeigt hier ein Vektor ins Leere?

    MfG

    void CGuy::addAnimation(int width, int height)
    {
    	itsAnimation.push_back(CAnimation(width, height));
    }
    
    CAnimation* CGuy::getAnimationObj (int aniIndex)
    {
    	// Abbruchbedingungen
    	if ((aniIndex < 0) || (aniIndex >= itsAnimation.capacity()))
    		return NULL;
    
    	return &itsAnimation[aniIndex];
    };
    
    void CAnimation::addFrame()
    {
    	BITMAP * temp = create_bitmap(itsWidth, itsHeight);
    	clear_to_color(temp, COLOR_WHITE);
    	itsFrame.push_back(temp);
    }
    

    Die letzte Methode hier geht, wie sie soll. Hab schon eine Animation mit vielen Frames erstellt.

    CGuy keen;
    keen.addAnimation(50, 50); keen.getAnimationObj(0)->addFrame();
    keen.addAnimation(50, 50); keen.getAnimationObj(1)->addFrame();
    

    Nach dem Beenden kommt eben der besagte Fehler. Es geht jedoch noch weiter:

    void CGuy::draw(BITMAP * surface)
    {
    // Anmerkung: itsCurrentAnimation = 0
    	if ((itsCurrentAnimation == -1) || (itsAnimation.capacity() == 0))
    		return;
    
    	masked_blit(itsAnimation[itsCurrentAnimation].getNextFrame(), 
    		surface, 0, 0, 
    		itsPos.x - itsAnimation[itsCurrentAnimation].getHotspot().x, 
    		itsPos.y - itsAnimation[itsCurrentAnimation].getHotspot().y, 
    		itsAnimation[itsCurrentAnimation].getFrameWidth(), 
    		itsAnimation[itsCurrentAnimation].getFrameHeight());
    }
    

    Wenn ich dann folgendes mache:

    CGuy keen;
    keen.addAnimation(50, 50); keen.getAnimationObj(0)->addFrame();
    keen.addAnimation(50, 50); keen.getAnimationObj(1)->addFrame();
    keen.draw(backBuffer);
    

    Kommt folgender Fehler:

    Unbehandelte Ausnahme bei 0x0ac8a7f0 in keen.exe: 0xC000001D: Illegal Instruction.

    Irgendwas haut mit "itsAnimation.push_back(CAnimation(width, height));" nicht hin. Aber was?

    MfG



  • Habs jetzt auch schon mit Pointern in dem itsAnimation-Vektor versucht. Das ging bis 4 Animationen. Sobald ich eine 5. hinzufügen will, kommt ein addFrame(); ein Fehler. 😞

    MfG



  • 1. Du hast den Sinn von capacity() missverstanden. size() gibt die Anzahl der Elemente im Vektor.

    2. return &itsAnimation[aniIndex];
    Du solltest nie Pointer auf ein Element in einem vector zurückgeben, wenn sich der vector noch vergrößern kann. Genauso wie bei einem normalen Array, muss dann größerer Speicher alloziert werden und alle Elemente werden hinüberkopiert. Dann sind alle Pointer ungültig. Du musst also sicherstellen, dass während der Pointer benutzt wird, sich der vector nicht ändert.

    Ansonsten kann man dir ohne den ganzen Quelltext wenig helfen. Andererseits, wird sich das auch niemand durchlesen, wenn es zuviel ist.



  • @ponto wieso sollte er keine pointer/referenzen zurückgeben? vector tuts schließlich auch,also mit ner referenz arbeiten is kein problem, nur das abspeichern sollte man lassen(aber auch nur dann, wenn man in nächster zeit einfügeoperationen plant).

    CAnimation* CGuy::getAnimationObj (int aniIndex)
    {
        // Abbruchbedingungen
        if (aniIndex < 0 || aniIndex >= itsAnimation.size())
            return NULL;
    
        return &itsAnimation[aniIndex];
    };
    

    alternativ könntest du das verwenden:

    CAnimation& CGuy::getAnimationObj (int aniIndex)
    {
    
        return itsAnimation.at(aniIndex);
    };
    

    aber: wenn aniIndex>size ist,dann wird ein assert geworfen, dass heisst, dein programm geht übern jordan. das ist aber egal, solange du die informationen über die anzahl der frames über eine methode zugänglich machst



  • otze schrieb:

    @ponto wieso sollte er keine pointer/referenzen zurückgeben? vector tuts schließlich auch,also mit ner referenz arbeiten is kein problem, nur das abspeichern sollte man lassen(aber auch nur dann, wenn man in nächster zeit einfügeoperationen plant).

    Eigentlich meinte ich das auch so, hab mich nicht vernünftig ausgedrückt.


Anmelden zum Antworten