我有以下问题:
class Component
{
public:
virtual void update(){};
};
class TestComponent : public Component
{
void update()override;
};
class GameObject
{
public :
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
void GameObject::update()
{
for(auto comp : components)
{
//I want to call the derived update here without casting it to the derived class if possible
comp->update();
}
}
private:
std::vector<std::shared_ptr<Component>> components;
};
Somewhere else in my code:
GameObject go;
TestComponent comp;
go.addComponent(comp);
我只是假设当我将一个对象添加到Components的向量中时,我可以简单地对所有vectors元素调用update,并且它使用传递给addComponent的对象的重写更新。因此,对于上面的示例,我希望forloop调用我添加的TestComponent的更新,而不是基类的更新。但这不是正在发生的事情,所以我认为我错过了一些东西。 也许我的方法总体上是错误的。我不太确定我为此使用了共享指针吗? 朝正确方向的任何提示将不胜感激。
答案 0 :(得分:7)
向量中没有TestComponent
个对象。它们都是Component
。
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
在此函数中,您将创建一个新的Component
对象,该对象是您传入的Component
对象的TestComponent
子对象的副本。被称为object slicing。
您将需要避免复制对象或实现某种可克隆的接口。
为避免复制对象,可以执行以下操作:
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);
}
在这种情况下,main
和go
共享单个TestComponent
对象的所有权。如果要避免这种情况,可以实现一个可克隆的接口,以便对象知道如何复制自己:
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);
}
在这种情况下,您仍然可以进行复制,但是每个类都必须重写clone
方法。
关于shared_ptr
的问题:std::shared_ptr
是一个智能指针,它在多个所有者之间共享对象的所有权。一个或多个std::shared_ptr
拥有的对象只有在共享它的所有std::shared_ptr
对象的所有权都被破坏时才被破坏。如果您不需要这种行为,则std::unique_ptr
存在,并且性能会更高。 std::unique_ptr
为唯一所有权建模。一次只能有一个std::unique_ptr
对象可以引用一个对象,而当该std::unique_ptr
被销毁时,该对象也将被销毁。
在这种情况下,可以使用两种类型的智能指针:
std::shared_ptr
能够与其他所有者(也许是其他GameObject
)共享其组件的所有权,请使用GameObjects
。std::unique_ptr
拥有其组件的专有所有权,请使用GameObject
。在这种情况下,GameObject
仍然可以允许其他对象访问其组件,但是组件的生存期将与GameObject
答案 1 :(得分:1)
要使您的代码编译,只需添加另一种方法,其余都很好。由于update方法是虚拟的,并且基类不是抽象的,因此两者都可以调用update而不会出现任何问题。
void TestComponent::addComponent(const TestComponent & tcomp)
{
std::shared_ptr<Component> test = std::make_shared<TestComponent >(tcomp);
components.push_back(test);
}
编辑:要添加任何组件,派生类或基类,请使用以下方式:
void TestComponent::addComponent(std::shared_ptr<Component> comp)
{
components.push_back(comp);
}