将派生类 unique_ptr 的所有权转移给其抽象基类 unique_ptr

3
我想在多态情况下将派生类的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;
}

1
unique_ptr<Fruit> fruit = make_unique<Apple>("Rose"); 应该可以工作。 - JohnFilleau
3
“Fruit”需要一个虚析构函数,才能允许从基类指针销毁“Apple”。 - Raymond Chen
@Raymond 是的,没错。如果想要使用多态性,就应该在基类上声明虚析构函数,对吗? - JohnFilleau
2
@JohnFilleau 虚析构函数并非多态所必需的,但是在通过基类指针删除派生类对象时是必要的。 - Raymond Chen
@RaymondChen:听起来很有趣。在声明虚析构函数之后,如何将drviedm转换为based并再次转换回来?请回答,我会接受的。 - ark1974
显示剩余2条评论
2个回答

4
为了将一个由派生类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<Base>::get(),因为我们还不确定是否要释放所有权。如果这一步通过了,那么我们可以调用std::unique_ptr<Base>::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()));
    }

点此查看演示


选项2运行得非常好。我将经常使用它,这是否是最佳方式?无论如何感谢您。 - ark1974
@ark 最佳方法是根本不需要来回转换。在销毁或移动拥有资源的对象时,才真正需要在独占指针之间传递所有权。如果您尝试使用多态性,则不需要将资源保留为派生类。如果函数需要基础指针,您可以只需在派生独占指针上使用 .get() 而无需交换所有权。我们需要看到您实际的用例,以帮助您找出正确的方法来完成您正在尝试的操作。 - JohnFilleau

1
尝试移动赋值
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接