C ++ Сокращение использования указателей, необработанных или иным образом и / или возврат обнуляемых не указателей

Я пишу Игру на C ++ с использованием OpenGL и решил написать систему на основе компонентов, во многом похожую на Unity или Unreal Engine — для развлечения и для изучения того, как эти системы создаются / работают. Я дошел до того, что мне нужно реализовать Components и GameObjects, что я сделал довольно успешно.

Моя реализация работает … это не совсем то, что мне бы хотелось.
В настоящее время я сохраняю Компоненты как частный вектор указателей на компоненты и возвращаю компонент, когда он запрашивается.

Примеры:

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

Вверху: Мой 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

Выше: как я храню свои компоненты в классе GameObject, я могу просматривать их по индексу

Мои проблемы с этим подходом связаны с тем, как я реализовал свою функцию GetComponent (). Он возвращает указатель на Компонент и, возможно, nullptr, если такого Компонента не существует.

T *GetComponent()
{
if (m_components.count(typeid(T).name()) != 0)
{
return static_cast<T*>(m_components[typeid(T).name()]);
}
else
{
return nullptr;
}
}

Моя проблема здесь в том, что из-за возврата указателя я мог вызвать delete и удалить указатель. Это необработанные указатели, но я позаботился о том, чтобы они обрабатывались программой, когда GameObject уничтожен, так что, надеюсь (если только я не буду некомпетентен), не боюсь утечек памяти — но я бы предпочел вернуть ссылку из-за тот факт, что вы не можете вызвать «удалить» на них — чтобы избежать любых глупых ошибок, которые я могу сделать.

Я сделал переменные закрытыми, и GameObject обрабатывает удаление Компонентов, и я предпочел бы не позволять себе удалять что-либо из-за некомпетентности или тому подобное.

Я думал о возвращении unique_ptr, но я не уверен, что эта реализация будет предпочтительнее.

(В качестве дополнительного примечания мне нужна функция GetComponent (), которая возвращает какое-либо значение NULL или указывает, что такого компонента не существует)

2

Решение

Ваша идея сократить использование сырых указателей верна. Я думаю, что вы должны посмотреть в Библиотека EntityX и обратите внимание, как все реализовано. Там вообще нет указателей.

Для вашего случая вы должны сделать то же самое, что и EntityX делает — создать класс ComponentHandle со ссылкой (не указатель) на ваш компонент. Этот класс не управляет жизненным циклом вашего компонента. Это просто интерфейс для вашего компонента. Вы также можете перегрузить -> оператор для доступа к членам в вашем компоненте.

Удачи в C ++ и компонент-сущность-система.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]