I have an abstract class(Component)
and this class should be owned by another class(GameObject).
Every GameObject
has a vector of components.
Header:
class Component;
class GameObject{
public:
GameObject();
virtual ~GameObject();
void addComponent(std::unique_ptr<Component> component);
void addComponent(Component* component);
void removeComponent(std::unique_ptr<Component> component);
virtual void update();
std::string getInfo();
//return the first component of type T
template<typename T>
T* getComponent(){
for(auto& component : components){
if(dynamic_cast<T*>(component.get())){
return dynamic_cast<T*>(component.get());
}
}
return nullptr;
}
// return the component with the type T
template<typename T>
std::vector<T*> getComponents(){
std::vector<T*> components;
for(auto component : this->components){
if(dynamic_cast<T*>(component)){
components.push_back(dynamic_cast<T*>(component));
}
}
return components;
}
std::vector<std::unique_ptr<Component>> components;
};
class Component
{
private:
public:
Component() = delete;
virtual ~Component() = 0;
virtual std::string getInfo();
//the game object this component is attached to
GameObject* gameObject;
};
source:
std::string GameObject::getInfo() {
std::stringstream ss;
ss << typeid(*this).name();
for (Uint32 i = 0; i < this->components.size(); i ) {
ss << typeid(components[i]).name() << " " << this->components[i]->getInfo();
}
}
void GameObject::addComponent(std::unique_ptr<Component> component) {
components.push_back(std::move(component));
}
void GameObject::addComponent(Component* component) {
components.push_back(std::move(std::make_unique<Component>(*component)));
}
void GameObject::removeComponent(std::unique_ptr<Component> component) {
for (auto it = components.begin(); it != components.end(); it ) {
if (it->get() == component.get()) {
components.erase(it);
return;
}
}
}
ERROR: cannot instantiate abstract class. file: memory line 3416
CodePudding user response:
Your issue is here:
void GameObject::addComponent(Component* component) {
components.push_back(std::move(std::make_unique<Component>(*component)));
}
When you dereference component
, as far as the compiler knows you still just have a Component
, not the actual instantiation--it can't call the proper copy constructor.
The solution is to just deleted this member function entirely. You already have a version that takes a std::unique_ptr<Component>
, so require the user of GameObject
to provide the unique_ptr
in all cases.