There are no TestComponent objects in your vector. They are all Components.
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
In this function, you create a new Component object that s a copy of the Component sub-object of the TestComponent object you passed in. This is known as object slicing.
You will need to either avoid copying the objects or implement some sort of cloneable interface.
To avoid copying the object, you can do something like this:
class GameObject
{
public:
void addComponent(std::shared_ptr<Component> comp)
{
components.push_back(comp);
}
// ...
};
int main() {
GameObject go;
std::shared_ptr<TestComponent> testComponent = std::make_shared<TestComponent>();
go.addComponent(testComponent);
}
In this case, main and go share ownership of a single TestComponent object. If you want to avoid that, you could implement a clonable interface so that objects know how to copy themselves:
class Component
{
public:
virtual void update(){};
virtual std::shared_ptr<Component> clone() const
{
return std::make_shared<Component>(*this);
}
};
class TestComponent : public Component
{
void update() override;
std::shared_ptr<Component> clone() const override
{
return std::make_shared<TestComponent>(*this);
}
};
class GameObject
{
public:
void addComponent(const Component& comp)
{
components.push_back(comp.clone());
}
// ...
};
int main()
{
GameObject go;
TestComponent comp;
go.addComponent(comp);
}
In this case, you still make a copy, but every class has to override the clone method.
As for the question about shared_ptr: std::shared_ptr is a smart pointer that shares ownership of an object between multiple owners. An object owned by one or more std::shared_ptrs is only destroyed when all of the std::shared_ptr objects sharing ownership of it are destroyed. If you don't need this behavior, then std::unique_ptr exists and will be somewhat more performant. std::unique_ptr models unique ownership. Only one std::unique_ptr object can ever reference an object at a time, and the object is destroyed when that std::unique_ptr is destroyed.
Either type of smart pointer could be used in this situation:
- Use
std::shared_ptr if you want a GameObject to be able to share ownership of its components with other owners (perhaps other GameObjects).
- Use
std::unique_ptr if you want a GameObject to have exclusive ownership of its components. In this case the GameObject could still allow other objects to access its components, but the components' lifetimes would be tied to the lifetime of the GameObject