Список против вектора с абстрактными классами

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

Привет,

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

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

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

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

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(); }
};

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

Вот одна из моих функций 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++;
    }
}

Мы будем очень признательны за любые советы. Спасибо!

Вероятно, вам стоит остаться с std::vector. Список может вставлять и удалять элементы из любой позиции быстрее, но почти во всем остальном он будет медленнее, чем вектор. Вы пытаетесь использовать list<shot>::iterator вместо list<shot*>::iterator. Может быть, что-то еще не так, просто бегло посмотрел. Использование auto iter = shotsFired.begin() — хорошая идея в тех случаях, когда очевидно, к какому типу данных относится auto.

super 13.04.2019 07:13

@супер Спасибо! Это отличный совет. Теперь это работает.

Lee 13.04.2019 07:27

Возможно, вы захотите прочитать онлайн-книгу gameprogrammingpatterns и, в частности, gameprogrammingpatterns.com/update-method.html

Ian4264 13.04.2019 09:04

@Ian4264 Спасибо за рекомендацию! Я обязательно посмотрю на это.

Lee 14.04.2019 00:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

std::list больше похож на связанный список. Может использовать немного больше памяти на элемент, но определенно лучше для случайных вставок и удалений. Но использование list vs 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++;
        }
    }
}

Большое спасибо! Это было отличное объяснение, и оно отлично работает. Очень признателен.

Lee 13.04.2019 07:26

Другие вопросы по теме