Я пишу игру на C++ с использованием OpenGL и решил написать компонентную систему, похожую на Unity или Unreal Engine - для развлечения и чтобы узнать, как эти системы созданы/работают. Я дошел до того, что мне нужно реализовать Компоненты и GameObjects, которые я сделал довольно успешно.C++ Сокращение использования указателей, необработанных или других и/или возвращающих нулевых не указателей
Моя реализация работает ... это не совсем так, как мне бы хотелось. В настоящее время я храню компоненты как частный вектор указателей на компоненты и возвращает компонент, когда он запрашивается.
Примеры:
GetComponent<MeshRenderer>(); //Returns "MeshRenderer" Component as MeshRenderer*
AddComponent(new MeshRenderer(mesh)); //Adds component to vector + returns MeshRenderer*
компоненты являются рефераты классы и расширены компонентами, такими как MeshRenderer.
T *AddComponent(T *component)
{
component->parent = this;
m_components[typeid(T).name()] = component;
bool pushLocation = true;
for (unsigned int i = 0; i < m_component_locations.size(); i++)
if (m_component_locations.at(i) == typeid(T).name())
pushLocation = false;
if(pushLocation)
m_component_locations.push_back(typeid(T).name());
return GetComponent<T>();
}
Выше: My AddComponent(); Код, используемый для добавления компонентов - требуется указатель на компонент ...
std::unordered_map<std::string, Component*> m_components; //Holds the components
std::vector<std::string> m_component_locations; //Holds data on components, allows them to be indexed
Выше: Как хранить свои компоненты в классе геймобжекты, позволяет мне перебрать их по индексу
Мои проблемы с этот подход связан с тем, как я реализовал функцию GetComponent(). Он возвращает указатель на компонент и, возможно, nullptr, если такой компонент не существует.
T *GetComponent()
{
if (m_components.count(typeid(T).name()) != 0)
{
return static_cast<T*>(m_components[typeid(T).name()]);
}
else
{
return nullptr;
}
}
Моя проблема заключается в том, что из-за возврата указателя я мог бы вызвать удаление и удаление указателя. Это исходные указатели, но я уверен, что они будут обработаны программой, когда GameObject будет уничтожен так - надеюсь (если я не некомпетентен), не бойтесь утечки памяти, но я бы предпочел вернуть ссылку из-за тот факт, что вы не можете называть их «удалить», чтобы избежать любых глупых ошибок, которые я могу сделать.
Я сделал переменные private, и GameObject обрабатывает удаление компонентов, и я бы предпочел не позволять себе удалять что-либо из-за некомпетентности или тому подобного.
Я думал о возврате unique_ptr, но я не уверен, будет ли эта реализация предпочтительной.
(В качестве дополнительной записке, мне нужна функция GetComponent(), чтобы вернуть своего рода нуль или дать указание, что такой компонент не существует)
'typeid (T) .name()' вы не должны полагаться на это каким-либо образом, используйте его только для целей отладки, так как нет никаких гарантий относительно того, что именно это делает –
Хорошо, есть ли у вас какие-либо предложения по как я мог бы изменить его для одного и того же использования, но не полагаясь на 'typeid (t) .name()'? –
Вы можете использовать хеш-код или 'std :: type_index', см. Там в примечаниях: http://en.cppreference.com/w/cpp/language/typeid –