Список против вектора с абстрактными классами - PullRequest
0 голосов
/ 13 апреля 2019

Предупреждение: вопрос от кого-то неопытного:)

Привет,

Я делаю макет космических захватчиков для домашнего задания, и яработая над пулями, которые корабль и инопланетяне будут стрелять / сбрасывать.У меня есть абстрактный базовый класс для обработки всех пуль, с двумя производными классами - ракетой и бомбой.

Я изначально использовал вектор, но где-то читал, что список будет более эффективным, поскольку они будут добавлены, исняли так быстро (?).Тем не менее, я новичок в списках, и у меня возникли некоторые проблемы с этим.Честно говоря, я не совсем уверен, как или вообще я могу использовать список с абстрактным классом.

Я еще не реализовал класс бомбы, потому что я хочу, чтобы сначала работал класс ракеты..

Вот пример заголовка базового класса (выстрел) + ракета:

enum attackType { BOMB, MISSILE };

class shot
{
private:
    float xPos,
          yPos;
    attackType bombOrMissile;
public:
    shot(Vector2f pos, attackType b_OR_m);     // passed ship pos + who fired shot
    virtual void draw(RenderWindow & win) = 0; // draws bullet on screen
    virtual Sprite & getSprite() = 0;          // gives sprite information

};

class missile : public shot
{
private:
    Sprite missileSprite;
public:
    missile(Vector2f pos, Texture & t);
    void draw(RenderWindow & win);
    Sprite & getSprite();
};

У меня есть класс «Менеджер выстрелов», который управляет списком пуль.Он увеличивает / уменьшает список и изменяет позицию спрайта.

Заголовок:

class shotMgr
{
private:
    list<shot*> shotsFired;
    Texture missileTexture;
public:
    shotMgr(); // loads texture
    void shoot(attackType b_OR_m, Vector2f pos);
    void disappear();
    void move();
    void draw(RenderWindow& win);
    int getAmountFilled() { return shotsFired.size(); }
};

Мой главный вопрос: как я могу описать синтаксис здесь?Я извращаюсь, пытаясь обойтись с птр.Будет ли вектор в конечном итоге лучшим вариантом в этом случае, или я просто что-то не так делаю?

Вот одна из моих функций shotMgr, чтобы продемонстрировать, что я сейчас делаю (это не так.компиляции);другие функции похожи, синтаксически:

void shotMgr::disappear()
{
    list<shot>::iterator iter;
    for (iter = shotsFired.begin(); iter != shotsFired.end();)
    {
        if (iter->getSprite().getPosition().y < 0)
        {
            iter = shotsFired.erase(iter);
        }
        else
            iter++;
    }
}

Любой совет будет принята с благодарностью.Спасибо!

1 Ответ

1 голос
/ 13 апреля 2019

std::vector наиболее эффективно при добавлении и удалении в конце коллекции. Когда код вставляет или удаляет откуда-либо еще в векторе, все элементы с индексом больше, чем элемент, к которому осуществляется доступ, будет "двигаться". То есть при вставке все, что находится справа от этого элемента в массиве, должно «переместиться на единицу». Аналогично, при удалении все, что находится справа от удаляемого элемента, должно сдвинуться влево. Не отличается от того, если бы вы использовали обычный массив в качестве коллекции.

std::list больше похоже на связанный список. Может использовать немного больше памяти на элемент, но определенно лучше для случайных вставок и удалений. Но использование list против vector не является корнем вашей проблемы.

Что касается вашей ошибки компиляции. Вероятно, из-за этого:

list<shot>::iterator iter;

Вы объявляете итератор для list<shot>::iterator, но ваша коллекция имеет тип list<shot*>. Так что вы, вероятно, хотите list<shot*>::iterator. Давайте исправим вашу функцию. auto на помощь, чтобы вам не приходилось слишком много думать об этом.

void shotMgr::disappear()
{
    for (auto iter = shotsFired.begin(); iter != shotsFired.end();)
    {
        shot* ptrShot = *iter;

        if (ptrShot->getSprite().getPosition().y < 0)
        {
            iter = shotsFired.erase(iter);
        }
        else
        {
            iter++;
        }
    }
}
...