Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以在向量循环时调用派生类方法吗<;共享\u ptr<;基类>>;?_C++ - Fatal编程技术网

C++ 我可以在向量循环时调用派生类方法吗<;共享\u ptr<;基类>>;?

C++ 我可以在向量循环时调用派生类方法吗<;共享\u ptr<;基类>>;?,c++,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

我有以下问题:

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);
类组件
{
公众:
虚拟void update(){};
};
类TestComponent:公共组件
{
无效更新()覆盖;
};
类游戏对象
{
公众:
无效添加组件(组件和组件)
{
std::shared_ptr test=std::make_shared(comp);
组件。推回(测试);
}
void GameObject::update()
{
用于(自动补偿:组件)
{
//如果可能的话,我想在这里调用派生更新,而不将其强制转换为派生类
comp->update();
}
}
私人:
std::向量分量;
};
在我的代码中的其他地方:
游戏对象围棋;
测试组件组件;
go.addComponent(comp);
我只是假设,当我向组件向量添加一个对象时,我可以简单地调用所有向量元素上的update,它使用我传递到addComponent的对象的覆盖更新。因此,对于上面的示例,我希望forloop调用我添加的TestComponent的更新,而不是基类更新。但事实并非如此,所以我认为我遗漏了什么。 或者我的方法大体上是错误的。我真的不确定我是否为此使用了sharedpointer?
任何正确方向的提示都将不胜感激。

矢量中没有
TestComponent
对象。它们都是
组件
s

void addComponent(Component& comp)
{
    std::shared_ptr<Component> test = std::make_shared<Component>(comp);
    components.push_back(test);
}
在这种情况下,
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);
}
类组件
{
公众:
虚拟void update(){};
虚拟std::shared_ptr clone()常量
{
返回std::make_shared(*this);
}
};
类TestComponent:公共组件
{
无效更新()覆盖;
std::shared_ptr clone()常量覆盖
{
返回std::make_shared(*this);
}
};
类游戏对象
{
公众:
无效添加组件(常量组件和组件)
{
组件。推回(comp.clone());
}
// ...
};
int main()
{
游戏对象围棋;
测试组件组件;
go.addComponent(comp);
}
在这种情况下,您仍然要创建一个副本,但每个类都必须重写
clone
方法


关于
shared_ptr
std::shared_ptr
是一个智能指针,它在多个所有者之间共享对象的所有权。只有当共享其所有权的所有
std::shared_ptr
对象被销毁时,一个或多个
std::shared_ptr
对象所拥有的对象才会被销毁。如果您不需要这种行为,那么就存在
std::unique\u ptr
,性能会有所提高<代码>标准::唯一\u ptr模型唯一所有权。一次只能有一个
std::unique_ptr
对象引用一个对象,当该
std::unique_ptr
被销毁时,该对象将被销毁

在这种情况下,可以使用任一类型的智能指针:

  • 如果您希望
    游戏对象
    能够与其他所有者(可能是其他
    游戏对象
    )共享其组件的所有权,请使用
    std::shared_ptr
  • 如果希望游戏对象对其组件拥有独占所有权,请使用
    std::unique_ptr
    。在这种情况下,
    GameObject
    仍然可以允许其他对象访问其组件,但是组件的生命周期将与
    GameObject

要使代码编译,只需添加另一个方法,其余方法都可以。由于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(const TestComponent&tcomp)
{
std::shared_ptr test=std::make_shared(tcomp);
组件。推回(测试);
}
已编辑:要添加任何组件(派生类或基类),请使用以下方式:

void TestComponent::addComponent(std::shared_ptr<Component> comp)
{
    components.push_back(comp);
}
void TestComponent::addComponent(std::shared_ptr comp)
{
组件。推回(组件);
}

可能的副本也击败了我,但是我认为您没有强调第二个解决方案(即副本)如何违背使用共享ptr来完全回答问题的目的。@ChrisMc这取决于
游戏对象
类上存在的操作。在这个有限的示例中,您是对的,
unique\u ptr
是一个更好的选择,但OP可能希望其他对象能够检索并共享
游戏对象所拥有的组件的所有权,但出于某种原因,在添加组件时仍希望始终复制该组件。@Galik
自动编译
是共享的ptr的副本,而不是
测试组件
,因此没有切片。没有分歧。这是问题的倒数第二行“我真的不确定我是否为此使用了sharedpointer?”这是我建议您解决的所有问题。=)@我甚至没看到那句话。增加了一点。这可能适用于Testcomponent,但我希望有几十个不同的组件,为每个组件添加一个方法有点过分。但实际上我可以利用模板,对吗?@Wuceng:刚才编辑过,添加了不同的组件。
void TestComponent::addComponent(std::shared_ptr<Component> comp)
{
    components.push_back(comp);
}