C++ “向下转换” unique_ptr<Base> 到 unique_ptr<Derived>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21174593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Downcasting" unique_ptr<Base> to unique_ptr<Derived>
提问by d7samurai
I have a series of factories that return unique_ptr<Base>
. Under the hood, though, they are providing pointers to various derived types, i.e unique_ptr<Derived>
, unique_ptr<DerivedA>
, unique_ptr<DerivedB>
etc.
我有一系列返回的工厂unique_ptr<Base>
。引擎盖下,虽然,他们所提供的指针各种衍生类型,即unique_ptr<Derived>
,unique_ptr<DerivedA>
,unique_ptr<DerivedB>
等
Given DerivedA : Derived
and Derived : Base
we'd have:
鉴于DerivedA : Derived
,Derived : Base
我们将有:
unique_ptr<Base> DerivedAFactory() {
return unique_ptr<Base>(new DerivedA);
}
What I need to do is to "cast" the pointer from the returned unique_ptr<Base>
to some derived level (not necessarily the original internal one). To illustrate in pseudo code:
我需要做的是将指针从返回的“转换”unique_ptr<Base>
到某个派生级别(不一定是原始内部级别)。用伪代码说明:
unique_ptr<Derived> ptr = static_cast<unique_ptr<Derived>>(DerivedAFactory());
I'm thinking of doing this by releasing the object from the unique_ptr
, then using a function that casts the raw pointer and reassigns that to another unique_ptr
of the desired flavor (the release
would be explicitly done by the caller prior to the call):
我正在考虑通过从 释放对象unique_ptr
,然后使用一个函数来转换原始指针并将其重新分配给另一个unique_ptr
所需的风格(这release
将由调用者在调用之前明确完成):
unique_ptr<Derived> CastToDerived(Base* obj) {
return unique_ptr<Derived>(static_cast<Derived*>(obj));
}
Is this valid, or is / will there be something funky going on?
这是有效的,还是/是否会发生一些时髦的事情?
PS. There is an added complication in that some of the factories reside in DLLs that are dynamically loaded at run-time, which means I need to make sure the produced objects are destroyed in the same context (heap space) as they were created. The transfer of ownership (which typically happens in another context) must then supply a deleter from the original context. But aside from having to supply / cast a deleter along with the pointer, the casting problem should be the same.
附注。有一个额外的复杂性,因为一些工厂驻留在运行时动态加载的 DLL 中,这意味着我需要确保生成的对象在创建时在相同的上下文(堆空间)中被销毁。所有权的转移(通常发生在另一个上下文中)必须从原始上下文中提供一个删除器。但是除了必须与指针一起提供/转换删除器之外,转换问题应该是相同的。
采纳答案by Praetorian
I'd create a couple of function templates, static_unique_ptr_cast
and dynamic_unique_ptr_cast
. Use the former in cases where you're absolutely certain the pointer is actually a Derived *
, otherwise use the latter.
我会创建几个函数模板,static_unique_ptr_cast
并且dynamic_unique_ptr_cast
. 在您绝对确定指针实际上是 a 的Derived *
情况下使用前者,否则使用后者。
template<typename Derived, typename Base, typename Del>
std::unique_ptr<Derived, Del>
static_unique_ptr_cast( std::unique_ptr<Base, Del>&& p )
{
auto d = static_cast<Derived *>(p.release());
return std::unique_ptr<Derived, Del>(d, std::move(p.get_deleter()));
}
template<typename Derived, typename Base, typename Del>
std::unique_ptr<Derived, Del>
dynamic_unique_ptr_cast( std::unique_ptr<Base, Del>&& p )
{
if(Derived *result = dynamic_cast<Derived *>(p.get())) {
p.release();
return std::unique_ptr<Derived, Del>(result, std::move(p.get_deleter()));
}
return std::unique_ptr<Derived, Del>(nullptr, p.get_deleter());
}
The functions are taking an rvalue reference to ensure that you're not pulling the rug out from underneath the caller's feet by stealingthe unique_ptr
passed to you.
该功能正在服用右值引用,以确保你没有从主叫方的脚下拉了地毯偷的unique_ptr
传递给你。