首页  >  文章  >  后端开发  >  如何在 C 中安全地将 `unique_ptr` 向下转换为 `unique_ptr` ?

如何在 C 中安全地将 `unique_ptr` 向下转换为 `unique_ptr` ?

Barbara Streisand
Barbara Streisand原创
2024-11-19 20:37:03711浏览

How to Safely Downcast a `unique_ptr` to `unique_ptr` in C  ?

向下转型 unique_ptr; to unique_ptr

在面向对象编程领域,继承在促进代码重用和可扩展性方面发挥着关键作用。然而,可能会出现需要“向下转换”unique_ptr的情况。 unique_ptr 的对象对象,可能具有不同的删除器函数。

为了解决这一挑战,请考虑一个假设场景,其中应用程序使用多个工厂,每个工厂生成 unique_ptr 。实例。这些工厂可以在内部提供对各种派生类型的访问,例如unique_ptr、unique_ptr或unique_ptr。举例说明:

unique_ptr<Base> DerivedAFactory() {
    return unique_ptr<Base>(new DerivedA);
}

目标是将返回的 unique_ptr 内的指针转换为派生类型,即使它与原始内部类型不同。人们可以用伪代码想象这一过程:

unique_ptr<Derived> ptr = static_cast<unique_ptr<Derived>>(DerivedAFactory());

但是,这种方法存在潜在的陷阱。更稳健的解决方案涉及从 unique_ptr 释放对象,将原始指针转换为所需的派生类型,并将其重新分配给新的 unique_ptr 类型。使用适当的删除器。

unique_ptr<Derived> CastToDerived(Base* obj) {
    return unique_ptr<Derived>(static_cast<Derived*>(obj));
}

只要对象从 DLL 动态加载并从同一上下文释放,此转换过程就应该保持有效。但是,在不同上下文之间转移所有权时,必须注意在指针旁边提供正确的删除器。

为了增加安全性和灵活性,建议使用函数模板进行转换:

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 不会无意中从调用者那里窃取,同时提供静态和动态转换选项。当已知指针是派生*而无需动态转换时,可以使用静态版本,而动态版本使用dynamic_cast执行运行时检查。

以上是如何在 C 中安全地将 `unique_ptr` 向下转换为 `unique_ptr` ?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn