我有以下问题:
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);
我只是假设,当我将一个对象添加到组件 vector 时,我可以简单地调用所有 vector 元素的更新,它使用我传递到 addComponent 的对象的覆盖更新。因此,对于我上面的示例,我希望 forloop 调用我添加的 TestComponent 的更新而不是基类更新。但这不是正在发生的事情,所以我认为我遗漏了一些东西。 或者,也许我的方法通常是错误的。我不太确定我为此使用了共享指针吗? 任何正确方向的提示都将不胜感激。
最佳答案
没有 TestComponent
vector 中的对象。都是Component
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
在此函数中,您创建一个新的 Component
对象是 Component
的拷贝 TestComponent
的子对象您传入的对象。这称为 object slicing .
您需要避免复制对象或实现某种可克隆接口(interface)。
为了避免复制对象,你可以这样做:
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
目的。如果你想避免这种情况,你可以实现一个可克隆的接口(interface),以便对象知道如何复制自己:
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
s 仅在所有 std::shared_ptr
被销毁时被销毁共享它的所有权的对象被销毁。如果您不需要此行为,则 std::unique_ptr
存在并且性能会更高。 std::unique_ptr
模型独特的所有权。只有一个std::unique_ptr
object 一次可以引用一个对象,当该对象被销毁时 std::unique_ptr
被摧毁。
在这种情况下可以使用任何一种类型的智能指针:
- 使用
std::shared_ptr
如果你想要GameObject
能够与其他所有者(可能是其他GameObjects
)共享其组件的所有权。 - 使用
std::unique_ptr
如果你想要GameObject
拥有其组件的专有所有权。在这种情况下GameObject
仍然可以允许其他对象访问其组件,但组件的生命周期将与GameObject
的生命周期相关联
关于c++ - 我可以在循环 vector<shared_ptr<BaseClass>> 时以某种方式调用派生类方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53347058/