pekfos |
» 2024-10-11 16:23:16 for( auto & nature: natures ) { auto it = std::find( natures.begin(), natures.end(), nature ); if( it != natures.end() ) { natures.erase( it ); delete nature; } }
natures.clear(); Ten kod nie ma sensu. Wyszukujesz obiekt w kontenerze, z którego go wziąłeś, więc warunek jest zawsze prawdziwy. Wywołanie erase() jest tu błędne, bo sprawia że pomijasz w pętli następny obiekt. Wywołanie clear() na końcu jest wystarczające, szybsze i nie interferuje z pętlą. Powinno być for( auto & nature: natures ) delete nature;
natures.clear(); Analogiczna sytuacja ma miejsce w ~Chunk() i deleteGameObject(). Usuwanie elementów z kontenera po którym iterujesz wymaga uważnej implementacji: for( auto it = v.begin(); it != v.end(); ) { if( deleteItem ) it = v.erase( it ); else ++it; } Przykładowo jak masz elementy o indeksach 0, 1, 2, 3, 4 i chcesz usunąć 2, to pętla powinna odwiedzić indeksy 0, 1, 2, 2, 3. Bo gdy usuniesz element pod indeksem 2, to element pod starym indeksem 3 staje się elementem o indeksie 2. Jeśli polecisz naiwnie indeksy od 0 do rozmiaru minus jeden, to odwiedzisz 4 elementy zamiast pięciu. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-12 03:56:07 Czyli, że jak. To jest wystarczające ? Zlokalizowałem gdzie mi pamięć cieknie. void load( string filename = "world/world.txt" ) { for( auto & chunk: chunks ) { delete chunk; } chunks.clear(); for( auto & go: gameObjects ) delete go; gameObjects.clear(); natures.clear(); itemsOnMap.clear(); inventoriesOnMap.clear(); paths.clear(); monsters.clear(); furnitures.clear(); walls.clear(); characters.clear(); buildings.clear(); }
if( objectType == "Chunk" ) { short x, y; string temp; getline( lineStream, temp, '=' ); lineStream >> y; getline( lineStream, temp, '=' ); lineStream >> x; chunk = getChunk( x, y ); short value; for( short y = 0; y < 16; y++ ) { for( short x = 0; x < 16; x++ ) { file >> value; chunk->terrain->edit( x, y, value ); } } } else if( chunk != nullptr ) { short x, y; string temp; string objectName; getline( lineStream, temp, '"' ); getline( lineStream, objectName, '"' ); getline( lineStream, temp, '=' ); lineStream >> y; getline( lineStream, temp, '=' ); lineStream >> x; cout << objectType << " \"" << objectName << "\" " << x << " " << y << "\n"; if( objectType == "Character" ) { Character * character = new Character( getPrefab( objectName ), x, y ); chunk->_characters.push_back( character ); } if( objectType == "Nature" ) { Nature * nature = new Nature( getPrefab( objectName ), x, y ); chunk->_natures.push_back( nature ); } |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-12 04:14:15 Tak jak wcześniej pisałem, pamięć cieknie dla obiektów typu "Character". Może źle je usuwam ? class Character : public Unit { public: Item * helmet; Item * armor; Item * pants; Item * leftHand; Item * rightHand; Texture * helmetIdleTextures[ 16 ]; Texture * helmetRunTextures[ 16 ]; Texture * helmetAttackTextures[ 16 ]; Texture * armorIdleTextures[ 16 ]; Texture * armorRunTextures[ 16 ]; Texture * armorAttackTextures[ 16 ]; Texture * pantsIdleTextures[ 16 ]; Texture * pantsRunTextures[ 16 ]; Texture * pantsAttackTextures[ 16 ]; Texture * leftHandIdleTextures[ 16 ]; Texture * leftHandRunTextures[ 16 ]; Texture * leftHandAttackTextures[ 16 ]; Texture * rightHandIdleTextures[ 16 ]; Texture * rightHandRunTextures[ 16 ]; Texture * rightHandAttackTextures[ 16 ]; sf::Sprite helmetSprite; sf::Sprite armorSprite; sf::Sprite pantsSprite; sf::Sprite leftHandSprite; sf::Sprite rightHandSprite; Dialogue * dialogue; Texture * talkWithTexture; sf::Sprite talkWithSprite; bool showHand; Character( string name, string bodySet = "sets/body/hero" ) : Unit( name, bodySet, 36, 18, 64 ) { type = gameObjectType::Character; helmet = nullptr; armor = nullptr; pants = nullptr; leftHand = nullptr; rightHand = nullptr; loadBody(); loadHelmet(); loadArmor(); loadPants(); loadLeftHand(); loadRightHand(); dialogue = nullptr; talkWithTexture = getTexture( "GUI/talk" ); talkWithSprite = sf::Sprite(); talkWithSprite.setTexture( * talkWithTexture->texture ); talkWithSprite.setOrigin( talkWithTexture->cx, talkWithTexture->cy ); showHand = false; } Character( GameObject * object, float x, float y ) : Unit( object, x, y ) { type = gameObjectType::Character; helmet = dynamic_cast < Character * >( object )->helmet; armor = dynamic_cast < Character * >( object )->armor; pants = dynamic_cast < Character * >( object )->pants; leftHand = dynamic_cast < Character * >( object )->leftHand; rightHand = dynamic_cast < Character * >( object )->rightHand; loadBody(); loadHelmet(); loadArmor(); loadPants(); loadLeftHand(); loadRightHand(); dialogue = dynamic_cast < Character * >( object )->dialogue; talkWithTexture = getTexture( "GUI/talk" ); talkWithSprite = sf::Sprite(); talkWithSprite.setTexture( * talkWithTexture->texture ); talkWithSprite.setOrigin( talkWithTexture->cx, talkWithTexture->cy ); showHand = false; } ~Character() { } }; |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-12 04:31:38 Rozwiązanie jest proste. Wystarczyło zmienić destruktor na virtualny. Teraz musze wszystkie pozostałe klasy naprawić |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-12 06:48:32 |
|
pekfos |
» 2024-10-13 11:37:58 Rozwiązanie jest proste. Wystarczyło zmienić destruktor na virtualny. Konkretnie to chcesz mieć wirtualny destruktor w klasie, która będzie typem wskaźnika na którym chcesz wykonywać delete, lub w klasie bazowej tej klasy. Najlepiej niech to będzie klasa bazowa na szczycie hierarchii, wtedy możesz użyć dowolnego poprawnego typu wskaźnika. |
|
1 « 2 » |