在新对象

时间:2017-11-24 03:19:14

标签: c++ vector

我有一个Entity类,所有对象(MissilesSpacesshipStarsExplosions)都会继承,并且每当创建这些类的实例时,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;
            }
        }
    }
}

2 个答案:

答案 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)事物