好的,为了说明我遇到的问题,我将展示一些(伪)代码。
假设我有以下型号:
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>>
。这甚至可以起作用吗?
有人可以解释一下为什么我不能做这种多态,如果可能的话,这是一个很好的解决方案,所以我可以做到这一点。
谢谢,感谢任何帮助!
答案 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.
Derived
是Base
的子类型并不意味着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
功能。