考虑以下简单代码:
#include <memory>
template<typename T>
struct Foo
{
virtual T & foo() = 0;
};
struct Bar : public Foo<int>
{
int x;
virtual int & foo() override
{
return x;
}
};
void baz(std::unique_ptr<Foo<int>>)
{
}
int main()
{
auto up = std::make_unique<Bar>();
baz(up);
return 0;
}
它不会编译报告此错误:
prog.cc:27:9: error: could not convert 'up' from 'unique_ptr<Bar,default_delete<Bar>>' to 'unique_ptr<Foo<int>,default_delete<Foo<int>>>'
27 | baz(up);
| ^~
| |
| unique_ptr<Bar,default_delete<Bar>>
我想知道如何解决这个问题。 share_ptr
似乎有适当的转换方法来解决此问题,而对于unique_ptr
似乎没有其他选择。
答案 0 :(得分:2)
首先,您要在baz
中按值取值 ,这意味着复制一个std::unique_ptr
,并且...不可能(或std::move
完成它,但我怀疑那是您想要的)。
第二,std::unique_ptr
不会转换,因为这将需要复制。
有什么解决方法?
您可以这样做:
std::unique_ptr<Foo<int>> up = std::make_unique<Bar>();
代替:
auto up = std::make_unique<Bar>();
并通过引用接受baz
中的参数:
void baz(std::unique_ptr<Foo<int>>&) { ... }
第一件事是保存unique_ptr
派生到unique_ptr
的基础。 auto
无法做到这一点,除非您使用强制转换。
如前所述,第二件事是不复制 unique_ptr
。
此外,您的代码会表现出未定义的行为,因为您使用基类指针删除了派生类对象。这需要基类中有一个virtual
析构函数。