vector klasa niszczy sama siebie

0
class brick 
{
private:
bool destroyable;
public:
brick();
~brick();
void onCollision()
{
// auto destrukcja 
}
};

 std::vector<brick> bricks;

Jak sprawić aby klasa zniszczyła/usunęła się z vectora po wywołaniu funkcji onCollision?
Próbowałem zrobić to za pomocą destruktora ale nic z tego

2
void onCollision(std::vector<brick> &bricks)
  {
   size_t last=bricks.size()-1;
   for(size_t i=0;i<=last;++i)
     {
      if(this==&bricks[i])
        {
         std::swap(bricks[i],bricks[last]);
         bricks.resize(last);
         return;
        }
     }
   cerr<<"Nie znaleziono na liście"<<endl;
   exit(1);
  }
1

Według mnie jeśli nie ma żadnych przeciwwskazań to lepiej jest dodać do obiektu pole bool o nazwie na przykład toDelete, które mówiło by o tym, czy obiekt powinien zostać zniszczony/usunięty. Wtedy możesz (w czasie liniowym) usunąć wszystkie elementy, które mają być usunięte (np używając fajnego erase-remove idiom http://en.wikipedia.org/wiki/Erase-remove_idiom)
Mógłbyś to robić wtedy w jakimś miejscu nadrzędnym. Tzn. np w klasie zarządzającej grą, czy choćby samymi kolizjami. Raz na tick/update.

1

Jedna z opcji jest taka jak napisał @Sopelek i @_13th_Dragon. Według mnie to klocki powinny być typu list lub set a nie vector jeśli planujesz je tak usuwać:
set<brick*> bricks;
potem w destruktorze piszesz coś w stylu:
bricks.remove(this);

jeszcze lepszą opcją by było, gdyby element nie decydował kiedy zostanie usunięty z kontenera i jakbyś przeniósł logikę gdzieś indziej (tam gdzie wywołujesz onCollision)

W przypadku metody @_13th_Dragon pamiętaj, żeby iterować po klockach od tyłu i dobrze jakby klocek znał swój indeks, żeby nie trzeba było iterować - proponuje jednak w dowolnym przypadku zostawić optymalizacje na koniec i skupić się na poprawnie działającym kodzie

0

dlatego zamiast set list czy vector mapa jest najlepsza do zarządzania Bricksami:

drobny przykład jakby to miało wyglądać:

#include <iostream>
#include <map>

class Brick
{
public:
	Brick(int id, bool destructable) : id_(id), destructable_(destructable)
	{}

	bool isDestructable() { return destructable_; }
private:
	int id_;

	bool destructable_;
};

using id = int;
using bricks = std::map<id, Brick>;

void collisionWithObjectId(bricks& bricksMap, int id)
{
	auto it = bricksMap.find(id);
	if(it != std::end(bricksMap)) {
		if(it->second.isDestructable()) {
			bricksMap.erase(it);
			std::cout << "Brick " << id << " has been destroyed.\n";
		} else {
			std::cout << "Brick " << id << " can't be destroyed.\n";
		}
	} else {
		std::cout << "Error -> no such brick id -> " << id << std::endl;
	}
}

int main()
{
	bricks bricksMap;
	bricksMap.emplace(0, Brick(0, true));
	bricksMap.emplace(1, Brick(1, false));
	bricksMap.emplace(2, Brick(2, true));
	bricksMap.emplace(3, Brick(3, false));

	collisionWithObjectId(bricksMap, 2);
	collisionWithObjectId(bricksMap, 3);
	collisionWithObjectId(bricksMap, 0);
	collisionWithObjectId(bricksMap, 5);
	collisionWithObjectId(bricksMap, 1);

	std::cout << "Bricks count that left: " << bricksMap.size();
	return 0;
}

http://melpon.org/wandbox/permlink/Xe0lVTjG4Nu7VSDC

naturalnie możnaby opakować mapę i funkcje w jakąś inną klasę to zarządzania tym bajzlem i zrobić z Brick unique_ptr'y

1 użytkowników online, w tym zalogowanych: 0, gości: 1