【问题标题】:Transfer ownership of a derived class unique_ptr to its abstract base class unique_ptr将派生类 unique_ptr 的所有权转移到其抽象基类 unique_ptr
【发布时间】:2022-01-24 04:01:58
【问题描述】:

我想在多态情况下将派生类 unique_ptr 的所有权转移到其抽象基类 unique_ptr。怎么办?

class Fruit {
public:
    virtual void print() = 0;
};

class Apple: public Fruit {
public:
    string name;
    virtual  void print()  { cout << " Apple name is " << name << endl; }
    Apple(string name): name(name) {}
};


int main()
{
    unique_ptr<Apple> apple = make_unique<Apple>("Rose");
    unique_ptr<Fruit> fruit = dynamic_cast<unique_ptr<Fruit>>(apple); // don't work
    // want to transfer ownership of apple to fruit

    unique_ptr<Apple> new_apple = dynamic_cast<unique_ptr<Apple>>(fruit); // get back the ownership to the new apple
    return 0;
}

【问题讨论】:

  • unique_ptr&lt;Fruit&gt; fruit = make_unique&lt;Apple&gt;("Rose"); 应该可以工作
  • 虽然它在原始指针中很容易,但使用智能指针从派生类到基类以及反之亦然的穿梭是一个问题。
  • @JohnFilleau Fruit 需要一个虚拟析构函数来允许 Apple 从基类指针中销毁。
  • @Raymond 确实如此。如果想要使用多态性,应该在基类上声明一个虚拟析构函数,对吗?
  • @JohnFilleau 多态不需要虚拟析构函数。如果通过指向基类的指针删除派生类,则需要它。

标签: c++ unique-ptr


【解决方案1】:

要将由派生类unique_ptr 管理的派生类的所有权转移到基类unique_ptr,您可以(并且应该)使用移动语义。

    std::unique_ptr<Derived> foo = std::make_unique<Derived>();
    std::unique_ptr<Base> bar = std::move(foo);

要将所有权归还给派生的unique_ptr,您需要稍微麻烦一点:

    std::unique_ptr<Derived> foo = std::make_unique<Derived>();
    std::unique_ptr<Base> bar = std::move(foo);

    std::unique_ptr<Derived> biz(static_cast<Derived*>(bar.release()));

如果您不确定指针的实际类型,则可以使用动态转换来检查它是否正确。请注意,我们在条件中使用std::unique_ptr&lt;Base&gt;::get(),因为我们还不确定是否要释放所有权。如果通过了,那么我们可以拨打std::unique_ptr&lt;Base&gt;::release()。

    std::unique_ptr<Derived> foo = std::make_unique<Derived>();
    std::unique_ptr<Base> bar = std::move(foo);

    // dynamic cast if we're unsure that it is castable
    if (dynamic_cast<Derived*>(bar.get())) {
        foo.reset(static_cast<Derived*>(bar.release()));
    }

see it in action

【讨论】:

  • 选项 2 就像魅力一样。我会经常使用它,这是最佳方式吗?无论如何,谢谢。
  • @ark 最佳方法是根本不来回投射。只有在拥有资源的对象被销毁或移动时,才真正应该在唯一指针之间转移所有权。如果您尝试使用多态性,那么您不需要将资源作为派生类保存。如果一个函数需要一个基指针,您可以只在派生的唯一指针上.get() 而无需交换所有权。我们需要查看您的实际用例,以帮助您找出正确的方法来做任何您正在尝试的事情。
【解决方案2】:

尝试移动分配

int main()
{
    unique_ptr<Apple> apple = make_unique<Apple>("Rose");
    unique_ptr<Fruit> fruit = std::move(apple);
    fruit->print();
    // want to transfer ownership of apple to fruit
    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 2021-11-26
    • 2023-03-17
    • 2017-03-23
    • 2013-07-02
    • 2021-07-16
    相关资源
    最近更新 更多