无法将派生类存储在基类的指针向量中

时间:2018-08-19 12:58:54

标签: c++ class c++11 smart-pointers stdvector

我有这个收藏:

vector<unique_ptr<Light>>* lights;

我有Light类的许多后代,例如DirectionalLightPointLight等。

我希望像这样将Light的所有后代存储在该lights vector中:

template<typename T>
unique_ptr<T> CreateLight()
{
    static_assert(std::is_base_of<Light, T>::value, "Type must of descendant of type Light. ");
    unique_ptr<T> light(new T());
    lights->emplace_back(light);
    return light;
}

此方法的原因是,我将灯光存储在renderer的集合中,这将尽其魔力使灯光影响着色器。

编辑

这些集合是名为Scene的类的一部分。我一直都需要它们,并且需要在堆上具有所有Light实例(以及Scene类具有的所有其他实例)。 Renderer的每一帧都将经过灯光集合,以随之影响场景对象的着色器。在任何给定时间访问此向量至关重要。

尽管如此,我仍然需要引用场景中的灯光,以便可以操纵其属性。

错误消息是这样的:

Severity    Code    Description Project File    Line    Suppression State
Error   C2664   'std::unique_ptr<Light,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::unique_ptr<DirectionalLight,std::default_delete<_Ty>>' to 'std::nullptr_t'

这在构建期间失败,而不是运行时。 我当然看了this one之类的答案,但无济于事。

我需要协助才能解决此问题。

3 个答案:

答案 0 :(得分:2)

lights->emplace_back(light);

更改为:

lights->emplace_back(new T());

答案 1 :(得分:2)

  

我有Light类的许多子孙,例如DirectionalLight,   PointLight,依此类推。我希望将Light的所有后代存储在   像这样点亮向量。

然后,您只需要一个unique_ptr<Light>的向量,而不是指向unique_ptr<Light>的向量的指针;这是一种过度设计的做事方式。

std::vector< std::unique_ptr<Light> > lights;

然后,您可以轻松处理所有事情。

template<typename T>
void CreateLight()
{
   static_assert(std::is_base_of<Light, T>::value, "Type must of descendant of type Light. ");
   // store to vector directly
   lights.emplace_back( std::make_unique<T>(/*args*/));
}
  

如何获取新创建的light实例,以便可以将其返回?

由于在lights向量的最后有一个新创建的实例,因此您可以在任何位置直接使用它。 See here

//Either directly
auto iter = lights.rbegin();
if(*iter) std::cout << "Done\n";

 // or
 auto lastElement = std::move(lights.back());
 if(lastElement) std::cout << "Done\n";

答案 2 :(得分:0)

您可以简单地返回对新创建对象的引用:

std::vector<std::unique_ptr<Light>>* lights;

template<typename T, typename... Args>
T& CreateLight(Args&&... args)
{
    ...
    auto light = std::make_unique<T>(std::forward<Args>(args)...);
    lights->push_back(std::move(light));
    return *static_cast<T*>(lights->back().get());
}

编辑。在阅读 JeJo 的答案后,修改CreateLight,使其接受任意数量(包括零个)的参数来构造{{1} }。

相关问题