EightiethPeak
EightiethPeak

Reputation: 197

C++ Reducing the use of pointers, raw or otherwise and/or returning nullable non-pointers

I am writing a Game in C++ using OpenGL and have decided to write a component based system, much alike Unity or Unreal Engine - for fun and to learn how these systems are made/work. I have reached the point where I need to implement Components and GameObjects, which I have done quite successfully.

My implementation works... it just isn't exactly how I would like it. Currently, I store the Components as a private vector of pointers to components and return a component when it is requested.

Examples:

GetComponent<MeshRenderer>(); //Returns "MeshRenderer" Component as MeshRenderer*
AddComponent(new MeshRenderer(mesh)); //Adds component to vector + returns MeshRenderer*

The Components are abstracts classes and are extended by components such as a 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>();
}

Above: My AddComponent(); code, used to add components - requires a pointer to a component...

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

Above: How I store my components in the GameObject class, allows me to loop through them by index

My issues with this approach are due to how I have implemented my GetComponent() function. It returns a pointer to the Component and, potentially, a nullptr if no such Component exists.

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

My issue here is that, due to returning a pointer, I could call delete and delete the pointer. These are raw pointers but I have made sure to ensure that they are handled by the program when the GameObject is destroyed so - hopefully (Unless I am being incompetent) no fear of memory leaks - but I'd prefer to return a reference due to the fact that you cannot call "delete" on them - to avoid any stupid mistakes that I may make.

I've made the variables private and the GameObject handles the deletion of Components and I'd prefer not to allow myself the ability to delete something due to incompetence or the like.

I have thought about returning a unique_ptr but I am unsure as to whether that implementation would be preferable.

(As an extra note, I do need the GetComponent() function to return some sort of null or give an indication that no such Component exists)

Upvotes: 2

Views: 242

Answers (1)

fnc12
fnc12

Reputation: 2237

Your idea of reducing use of raw pointers is right. I think you have to look into EntityX library and notice how things implemented. There are no pointers there at all.

For your case your have to do the same thing as EntityX does - create class ComponentHandle with reference (not pointer) to your component. This class does not manages life-cycle of your component. It is just an interface for your component. You can also overload -> operator for accessing members in your component.

Good luck in C++ and component-entity-system.

Upvotes: 1

Related Questions