Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

10.03.2010, 20:02

list::iterator zurücksetzen

hallo,
habe ein kleines problem. Ich möchte bei einer Animation eine Liste von Texturen durchgehen und wenn ich am Ende bin wieder von vorne, wie bei einer Animation halt.

So sieht das bei mir aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
void CAnimation::Show(CSprite* pSprite, int pCoordX, int pCoordY)
{
    int time = timeGetTime();

    if(time - LastChange >= PictureDuration && Running)
    {
        if(++Position == Textures.end()) Position = Textures.begin();
        LastChange = time;
    }

    pSprite->ShowTexture((*Position), pCoordX, pCoordY);
}


jetzt meint mir aber eine debug meldung zur laufzeit zu sagen, dass listiterator nicht inkrementierbar ist. Warum geht das denn nicht?

2

10.03.2010, 20:15

Ist die Liste möglicherweise zu einer Zeit leer? Wird der Iterator nur an dieser Stelle modifiziert? Und dass der Iterator nicht durch Löschungen oder Ähnliches ungültig wurde, hast du auch sichergestellt?

3

10.03.2010, 20:32

ich bin da eigentlich ziemlich sicher, ich kann euch mal den ganzen code zeigen, ist nicht so viel:

Animation.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CAnimation
{
    public:

        void Create(int pPictureDuration);
        void AddPicture(CTexture* pTexture);
        void Show(CSprite* pSprite, int pCoordX, int pCoordY);
        void Start();
        void Stop();
        void Reset();

    private:

        std::list<CTexture*> Textures;
        std::list<CTexture*>::iterator Position;

        int PictureDuration;
        int LastChange;

        bool Running;
};



Animation.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "global.h"

void CAnimation::Create(int pPictureDuration)
{
    PictureDuration = pPictureDuration;
    Position = Textures.begin();
}

void CAnimation::AddPicture(CTexture* pTexture)
{
    Textures.push_back(pTexture);
}

void CAnimation::Show(CSprite* pSprite, int pCoordX, int pCoordY)
{
    int time = timeGetTime();

    if(time - LastChange >= PictureDuration && Running)
    {
        if(++Position == Textures.end()) Position = Textures.begin();
        LastChange = time;
    }

    pSprite->ShowTexture((*Position), pCoordX, pCoordY);
}

void CAnimation::Start()
{
    Running = true;
}

void CAnimation::Stop()
{
    Running = false;
}

void CAnimation::Reset()
{
    Position = Textures.begin();
}

4

10.03.2010, 21:06

Du setzt den Iterator am Anfang auf begin(). Da der Container zu dieser Zeit leer ist, gilt begin() == end(). Wenn du ein Element einfügst, ändert sich der bestehende Iterator nicht, sondern zeigt immer noch auf end(). Eine Inkrementierung ist dann natürlich ungültig.

Create()- bzw. Init()-Methoden sehe ich hier immer wieder. Warum verwendest du nicht Konstruktoren? Damit könntest du eine Klasseninvariante aufrechterhalten.

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

5

10.03.2010, 21:10

Das ist äussert schlechtes Design.

Sehe gerade, dass Nexus bereits den Fehler gepostet hat. Zusätzlich zu den gefährlichen Init Funktionen machst du den internen Zustand der Klasse abhängig davon, ob der Benutzer Reset aufruft oder nicht. Das ist schlecht. Eine Klasse sollte für ihre Invarianz selbst verantwortlich sein.

Am besten speicherst du den Iterator nicht, sondern erzeugst in erst, wenn du ihn brauchst (also den auf begin).
Grundsätzlich sollte man Iteratoren nicht speichern, weil sie ungültig werden können, wenn eine andere Position verändert wird (also z.B etwas eingefügt wird). Im Falle von list ist das nicht so, aber du siehst, dass die Faustregel auch hier einen Fehler erspart hätte.

6

10.03.2010, 21:14

danke für deine hilfe, daran hat es gelegen, war natürlich ein doofer denkfehler^^ das mit den konstruktoren ist auch ne gute Idee, warum ne Create funktion schreiben wenn man einen konstruktor hat :)

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

7

10.03.2010, 21:20

Zitat von »"newby"«

danke für deine hilfe, daran hat es gelegen, war natürlich ein doofer denkfehler^^ das mit den konstruktoren ist auch ne gute Idee, warum ne Create funktion schreiben wenn man einen konstruktor hat :)

Genau. Und aufgeräumt wird im Destruktor!
Dann kann aucht fast nichts schief gehen. ;)

Werbeanzeige