我有一系列的工厂会返回unique_ptr<Base>
。但实际上,在内部它们提供了指向各种派生类型(unique_ptr<Derived>
, unique_ptr<DerivedA>
, unique_ptr<DerivedB>
等)的指针。
给定DerivedA : Derived
和Derived : Base
,我们有:
unique_ptr<Base> DerivedAFactory() {
return unique_ptr<Base>(new DerivedA);
}
我需要做的是将从返回的unique_ptr<Base>
中的指针“转换”为某个派生层次(不一定是原始内部层次)。举个伪代码的例子:
unique_ptr<Derived> ptr = static_cast<unique_ptr<Derived>>(DerivedAFactory());
我打算通过释放 unique_ptr
中的对象,然后使用一个将裸指针转换并重新分配给另一个所需类型 unique_ptr
的函数来完成此操作(在调用之前,release
会由调用者明确执行):
unique_ptr<Derived> CastToDerived(Base* obj) {
return unique_ptr<Derived>(static_cast<Derived*>(obj));
}
这个是否有效,或者会出现奇怪的事情发生?
PS. 增加了一个复杂性,在某些工厂中驻留在动态加载的DLL中,这意味着我需要确保生成的对象在与它们创建时相同的上下文(堆空间)中被销毁。所有权的转移(通常发生在另一个上下文中)必须从原始上下文提供删除器。除了必须提供/强制转换指针的删除器之外,转换问题应该是相同的。
CastToDerived
使用unique_ptr<T>&&
。之所以没有与shared_ptr
的static_pointer_cast
等效的转换,是因为通常转换不会修改其参数。但对于unique_ptr
,你必须将指针从参数移动到转换返回的对象中。 - dypswap
也可能是一个不错的选择。 - user2485710CastToDerived
函数可以通过CastToDerived(my_ptr.get())
(这是一个错误)和CastToDerived(my_ptr.release())
(这是正确的)来调用。为了防止前者,我建议使用像CastToDerived(std::move(my_ptr))
这样显式的方式,可能会更加明确,也不容易出错。或者,在名称上进行明确,比如move_static_cast<Derived>(my_ptr)
。 - dypmy_ptr.get()
。因此,在调用站点强制使用std::move
,或让转换函数移动指针,但这样做需要让转换函数的名称表明它会修改其参数。 - dyp