无法返回包含派生指针的向量

时间:2017-02-27 00:09:21

标签: c++ c++11

好的,为了说明我遇到的问题,我将展示一些(伪)代码。

假设我有以下型号:

class Animal : public GameObject;

class Player : public GameObject;

class GameObject : public ObjectInterface;

class ObjectInterface
{
public:
    virtual ~ObjectInterface() = default;
    virtual vec3 GetPosition() = 0;
}

现在我还拥有一些“对象上下文”,它包含某些游戏对象的集合。

class ContextObject
{
     // they implement ObjectInterface
     vector<shared_ptr<Animal>> animals;
     vector<shared_ptr<Player>> players; 
}

现在我有一个TargetSelector课程,它只能直接使用ObjectInterface

class TargetSelector
{
    // this is somehow not possible, although `animals` are a subclass of `ObjectInterface`
    vector<shared_ptr<Model::ObjectInterface>>& GetAvailableTargets()
    {
        return context->animals; // context is some `ObjectContext`
    }
}

我希望上面的代码能够正常运行,因为Animal属于ObjectInterface类型。但我得到一个错误,说它无法从vector<shared_ptr<Animal>>转换为vector<shared_ptr<ObjectInterface>>。这甚至可以起作用吗?

有人可以解释一下为什么我不能做这种多态,如果可能的话,这是一个很好的解决方案,所以我可以做到这一点。

谢谢,感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

  

我希望上面的代码能够正常运行,因为Animal的类型为ObjectInterface

不幸的是,课程模板不会那样工作。

鉴于

struct Base {};
struct Derived : Base {};

Derived d;
Base& bref = d; // OK.
Base  b = d;    // OK.

然而,鉴于

template <tpename T> Foo {};

Foo<Derived> d;
Foo<Base>& bref = d; // Not OK
Foo<Base> b = d;     // Not OK.

DerivedBase的子类型并不意味着Foo<Derived>Foo<Base>的子类型。

这个类比也适用于shared_ptr。使用另一层类模板会加剧您的问题。 shared_ptr<Derived>不是shared_ptr<Base>的子类型。在vector<shared_ptr<Derived>>被曝光时,别忘了能够使用vector<shared_ptr<Base>>

您可以在所有地方使用vector<shared_ptr<ObjectInterface>>,并确保在使用之前投射到相应的shared_ptr类型。

查看http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast处的各种pointer_cast功能。