为了账号安全,请及时绑定邮箱和手机立即绑定

“向下转换” unique_ptr <Base>到unique_ptr <Derived>

/ 猿问

“向下转换” unique_ptr <Base>到unique_ptr <Derived>

C++
MYYA 2019-11-14 14:46:32

我有一系列退货的工厂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中,这意味着我需要确保在与创建对象相同的上下文(堆空间)中销毁所生成的对象。所有权转移(通常发生在另一个上下文中)必须随后提供原始上下文中的删除器。但是除了必须提供/强制释放删除器以及指针之外,强制转换问题应该相同。


查看完整描述

3 回答

?
HUWWW

我将创建几个功能模板,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());

}

该功能正在服用右值引用,以确保你没有从主叫方的脚下拉了地毯偷的unique_ptr传递给你。


查看完整回答
反对 回复 2019-11-14
?
慕丝7291255

我一直在尝试使用此函数,并且在初始化unique_ptr(pastebin.com/EABRT9G3)时使用自定义删除程序时,它能够正常工作。但是,不确定如何使用默认删除器(pastebin.com/BNDBivff)-在这种情况下,编译器会抱怨派生类/基类删除器之间没有可行的转换。是否可以将此代码与默认delterter一起使用?如果是这样,您能否看一下我的第二个粘贴并让我知道我需要如何使用正确的模板参数来调用cast函数?谢谢:)

查看完整回答
反对 回复 2019-11-14
?
喵喔喔

您需要从源对象中提取删除程序,并将其注入到目标对象中。该类型很可能是不够的。

查看完整回答
反对 回复 2019-11-14

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信