我有一个Entity
类,所有对象(Missiles
,Spacesship
,Stars
,Explosions
)都会继承,并且每当创建这些类的实例时,Entity的构造函数将“this”添加到所有实例的向量列表中,如下所示:
std::vector<Entity*> Entity::instances;
Entity::Entity()
{
instances.push_back(this);
}
这很好用,因为我可以遍历每个实例并通过e-&gt; Render()或e-&gt; Update()等来执行它的方法。
奇怪的是,除了在一个特定的地方,它可以在其他地方使用。 它在这里工作: Core.cpp
for (int i = 0; i < 128; i++)
{
stars[i] = new Star();
stars[i]->position.x = rand() % (screenWidth + 1);
stars[i]->position.y = rand() % (screenHeight + 1);
stars[i]->angle = rand() % 360;
stars[i]->boundingbox.w = 2 + rand() % 7;
stars[i]->boundingbox.h = stars[i]->boundingbox.w;
}
for (int i = 0; i < 16; i++)
{
meteorites[i] = new Meteorite();
meteorites[i]->Spawn();
}
但是 ..它弹出'矢量迭代器不兼容'
Meteorite.cpp
void Meteorite::TakeDamage()
{
health -= 5;
if (health <= 0)
{
Missile* explo = new Missile();
explo->position.x = position.x;
explo->position.y = position.y;
Spawn();
}
}
我完全无能为力 - 这并不是说我以不同于通常的方式创建这些元素。
#EDIT 我认为这也很重要,Meteorite :: Update()可以检测碰撞并运行TakeDamage()来创建实例:
for each (Entity* e in Entity::instances)
{
if (e == this)
{
continue;
}
if (e->entClass == "ENTITY_MISSILE")
{
Missile* m = (Missile*)e;
if (abs(position.x - m->position.x) * 2 < (boundingbox.w + m-
>boundingbox.w))
{
if (abs(position.y - m->position.y) * 2 < (boundingbox.h + m-
>boundingbox.h))
{
TakeDamage();
break;
}
}
}
}
答案 0 :(得分:2)
请注意,当您调用push_back
on a std::vector
时,迭代器会失效(强调我的):
如果new size()大于capacity(),那么所有迭代器和引用(包括过去的迭代器)都将失效。否则只有过去的迭代器无效。
因此,当for
被调用TakeDamage
时,你构建一个Missile
(随后调用Entity::Entity()
和instances.push_back(this)
),你就会失效你的迭代器。
您需要通过索引而不是迭代器循环,或者跟踪哪些对象需要TakeDamage()
调用它们并在完成迭代后调用它们,或创建instances
的副本你迭代。
请注意,我从未见过语法for each (... in ...)
,但可能是使用了迭代器。
您提到问题中的代码是在Meteorite::Update
内运行的,您还提到了
这很好用,因为我可以遍历每个实例并通过e-&gt; Render()或e-&gt; Update()等来执行它的方法。
很可能您正在迭代所有instances
,调用Update
,并且在调用TakeDamage
内,这会使您的instances
无效。在迭代push_back
的同时在TakeDamage
内拨打instances
绝对是您的问题。
答案 1 :(得分:0)
尝试:_GLOBAL_OFFSET_TABLE_
代替您的for(Entity* e : Entity::instances)
事物