Как выполнить цикл for с итераторами, если векторный тип является родителем двух дочерних типов, заполняющих вектор

У меня есть проблема:

это мой цикл для ранее использованного дочернего типа

std::vector<Coin>::iterator coin;

for (coin = coinVec.begin(); coin != coinVec.end(); ++coin)
{

    sf::FloatRect coinBounds = coin->getGlobalBounds();

    if (viewBox.intersects(coinBounds))
    {

        if (playerBounds.intersects(coinBounds))
        {
            coin = coinVec.erase(coin);
            break;
        }
        else coin->setTextureRect(currentFrame);

    }
}

И аналогичный для std::vector<Heal>.

Я перестраиваю свою структуру кода так: Coin теперь является дочерним элементом Collectables.

Теперь есть только один вектор: std::vector<Collectables>, который содержит все объекты дочерних классов, такие как Coin, Heal и т. д.. Есть ли способ заставить код работать только с одним циклом и итераторами? Если да, то как бы вы это сделали?

Спасибо

Ну, мы не можем видеть соответствующий код, но вы не можете хранить полиморфные типы в таком векторе. Вы получите нарезка объекта.

Paul Sanders 28.03.2022 18:26

Я думаю, что это не будет проблемой, мой, например, класс Health не содержит объект типа Collectables, он наследует от него только 90% контента, совместно используемого с другими дочерними классами. И основное использование Collectables заключается в упрощении моего кода. Я могу использовать как, std::Vector<Collectables>... .push_back(healthObject); и это делает многое,

maxif1997 28.03.2022 18:47

Привет, maxif1997, рад узнать, что ты нашел решение этой проблемы! Пожалуйста, подумайте над тем, чтобы ответить на него и принять его как ответ, чтобы изменить его статус на «Отвечено». Это также поможет другим решить аналогичную проблему. См. можно я сам отвечу на свой вопрос.., просто напоминание :)

Yujian Yao - MSFT 04.04.2022 03:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
3
49
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Я обнаружил, что мой код настолько универсален, что мне вообще не нужно разделять элементы вектора.

Мое решение здесь:

std::vector<Collectables>::iterator collect;

for (collect = collectVec.begin(); collect != collectVec.end(); ++collect)
{

    sf::FloatRect collectBounds = collect->getGlobalBounds();

    if (viewBox.intersects(collectBounds))
    {

        if (playerBounds.intersects(collectBounds))
        {
            collect = collectVec.erase(collect);
            break;
        }
        else collect->setTextureRect(currentFrame);

    }
}

И если вам действительно нужно разделить элементы, попробуйте следующее:

if (collect->getType() == ResourceManager::enums::textures::coin)
{

} else
    if (collect->getType() == ResourceManager::enums::textures::health)
    {

    }

Где getType хранит просто значение int id, соответствующее значению перечисления.

Хотя кажется, что вы решили проблему, наверное, стоит рассказать, как бы вы решили первоначальную проблему. Как упоминалось в комментариях, хранение элементов в векторе приведет к нарезке объектов, например.

std::vector<BaseClass> vect;

Элементы вектора могли бы хранить информацию об объектах, которая является общей для классов, она же определена в BaseClass. Если вы хотите иметь возможность выполнять полиморфизм (чего вы пытаетесь достичь в примере), вы должны хранить вектор указателей, подобный этому.

std::vector<BaseClass*> vect; 

Каждый указатель будет указывать на адрес элемента, и, таким образом, нарезки объекта не произойдет.

Я попробовал ваш способ, но у меня проблема с использованием итератора в моем цикле for с этим вектором двойного указателя. Как бы Вы это сделали?

maxif1997 28.03.2022 19:39

Сначала у вас был итератор coin, который вы использовали как coin->some_member. Теперь, когда у вас есть итератор вектора указателей, вы могли бы сделать *(coin)->some_member

Karen Baghdasaryan 29.03.2022 17:59

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