c++ - 我可以在循环 vector<shared_ptr<BaseClass>> 时以某种方式调用派生类方法吗?

标签 c++

我有以下问题:

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);
}

在这种情况下,maingo股权单一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/

相关文章:

C++03.在编译时测试 rvalue-vs-lvalue,而不仅仅是在运行时

c++ - 使用最佳编译器标志和配置从 cmake 运行 Halide 生成器

c++ - c++中的重写函数

c++ - 使用 MinGW 编译 SFML 项目

c++ - 使用模板时,是否可以确定左值的类型?

c++ - 如何让 g++ 在终端中显示执行时间?

c++ - Libtiff:如何获取像素值或如何将 TIFF 文件转换为文本文件

c++ - SDL:体系结构 x86_64 的 undefined symbol

c++ flood fill图像递归算法错误

c++ - 无法使用 C++ 在 Windows 中为对象访问(文件夹)添加审核策略(ACE)