Это мой общий игровой цикл C ++:
std::vector<std::unique_ptr<State>> states;
while(window.isOpen())
{
//event checking and other stuff
for(size_t i = 0; i < states.size(); i++)
{
states[i]->Update();
//clear backbuffer
states[i]->Draw(window);
//draw backbuffer
}
}
Проблема в том, что всякий раз, когда я удаляю состояние из states
список сбоев программы. Я предполагаю, что это потому, что, как только состояние было удалено, вы больше не можете использовать объект, потому что его, очевидно, больше нет.
Я уверен, что лучший способ исправить это — скопировать состояния внутри states
вектор в новый и просто внести любые изменения, которые я хочу, чтобы states
вектор таким образом, никакие изменения не будут сделаны во время цикла.
Так вот что я придумал:
std::vector<std::unique_ptr<State>> states;
std::vector<State> tempStates;
while(window.isOpen())
{
//event checking and other stuff
for(size_t i = 0; i < states.size(); i++)
{
tempStates.push_back(*states[i]);
}
for(size_t i = 0; i < tempStates.size(); i++)
{
tempStates[i].Update();
//clear backbuffer
tempStates[i].Draw(window);
//draw backbuffer
}
tempStates.clear();
}
Но я получаю сообщение об ошибке при сборке приложения, говорящее error C2259: 'State' : cannot instantiate abstract class
в файле xmemory0
, «State» — это мой абстрактный базовый класс, от которого наследуются другие состояния. Я не понимаю, почему я получаю эту ошибку, потому что я не создаю экземпляр этого абстрактного класса, я создаю экземпляр класса, который наследуется от него. states
не полон State
объекты он полон объектов, которые наследуют от него, который, я думаю, сделал бы его полным State
объекты в некотором роде, но независимо от того, я не создаю их экземпляры.
Так почему я получаю эту ошибку и как я могу ее исправить?
Благодарю.
РЕДАКТИРОВАТЬ
Это в основном, как элемент внутри states
удаляется при использовании первого метода, описанного выше. Это внутри класса, который наследует от State
:
void Update()
{
if(/*whatever*/)
{
StateManager::RemoveState(std::unique_ptr<State>(this));
//call stack comes back here but cant because this no longer exists
}
}
StateManager.cpp
void StateManager::RemoveState(std::unique_ptr<State> state)
{
states.erase(std::remove(states.begin(), states.end(), state), states.end());
}
Возможно, было бы просто перечислить элементы, которые вы хотите удалить:
std::vector<unique_ptr<state>> states;
while ( /* stuff */)
{
std::vector<unique_ptr<state>> temp;
for (std::size_t i = 0; i != states.size(); ++i)
{
if ( /* move? */)
{
temp.push_back(std::move(states[i]));
}
}
for (std::size_t i = 0; i != temp.size(); ++i)
{
// process temp[i]
}
}
Удаленные элементы будут нулевыми указателями в states
вектор в конце каждого тела цикла, так что вы можете удалить их:
states.erase(std::remove(states.begin(), states.end(), nullptr), states.end());
(На данный момент нет никаких std::copy_if
а также std::move_if
алгоритмы, но как только они будут добавлены в стандартную библиотеку, этот код станет намного короче.)
Других решений пока нет …