У меня есть проблема:
это мой цикл для ранее использованного дочернего типа
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 и т. д.. Есть ли способ заставить код работать только с одним циклом и итераторами? Если да, то как бы вы это сделали?
Спасибо
Я думаю, что это не будет проблемой, мой, например, класс Health не содержит объект типа Collectables, он наследует от него только 90% контента, совместно используемого с другими дочерними классами. И основное использование Collectables заключается в упрощении моего кода. Я могу использовать как, std::Vector<Collectables>... .push_back(healthObject); и это делает многое,
Привет, maxif1997, рад узнать, что ты нашел решение этой проблемы! Пожалуйста, подумайте над тем, чтобы ответить на него и принять его как ответ, чтобы изменить его статус на «Отвечено». Это также поможет другим решить аналогичную проблему. См. можно я сам отвечу на свой вопрос.., просто напоминание :)
Я обнаружил, что мой код настолько универсален, что мне вообще не нужно разделять элементы вектора.
Мое решение здесь:
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 с этим вектором двойного указателя. Как бы Вы это сделали?
Сначала у вас был итератор coin
, который вы использовали как coin->some_member
. Теперь, когда у вас есть итератор вектора указателей, вы могли бы сделать *(coin)->some_member
Ну, мы не можем видеть соответствующий код, но вы не можете хранить полиморфные типы в таком векторе. Вы получите нарезка объекта.