【问题标题】:Convert unique_ptr<Derived> to unique_ptr<Base>将 unique_ptr<Derived> 转换为 unique_ptr<Base>
【发布时间】:2018-12-15 00:31:18
【问题描述】:

一个简单的代码

class Base {};
class Derived : Base {};

unique_ptr<Base> Create() {
    unique_ptr<Base> basePtr = make_unique<Derived>(); // compile error
    return basePtr;
}

产生编译错误(“没有合适的转换”)。我找到了similar question,解决方案是使用std::move。我试过这个

unique_ptr<Derived> derived = make_unique<Derived>();
unique_ptr<Base> basePtr = std::move(derived); // compile error

但现在std::move 产生编译错误。我还发现 question 哪里(如果我理解得很好)如果我们使用,演员应该是自动的

unique_ptr<Base> basePtr = make_unique<Derived>(new Derived()); //compile error

但这也不起作用(编译错误),并且recommended 也不能与智能指针一起使用new。

什么是正确的解决方案?

到目前为止我发现的唯一可行的解​​决方案

unique_ptr<Base> basePtr = unique_ptr<Base>((Base*)new Derived());

看起来真的很丑。

【问题讨论】:

    标签: c++ pointers unique-ptr


    【解决方案1】:

    您的类是从基类私有继承的。这是class 的默认值,而struct 的默认值是公共继承。这使得外部派生到基础的转换无效。 unique_ptr 通过公共继承 (live example) 很好地处理派生到基的转换:

     class Base {};
     class Derived : public Base {};
                     ^^^^^^
    

    如下所述,在使用unique_ptr 时向基类添加虚拟析构函数也很重要,因为多态破坏依赖于它来实现明确定义的行为。 shared_ptr 不需要这个,但这已经离题了。

    【讨论】:

    • 是的,这就是问题所在。我没有看到另一个问题使用结构。
    • Chris,将虚拟析构函数添加到 Base 中可能是值得的。就目前而言,这将导致上述用例中的 UB,因为 Derived 不会被正确破坏。
    【解决方案2】:

    pimpl 惯用语中经常使用该模式,因此需要使用虚拟析构函数。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。
    猜你喜欢
    • 2014-03-27
    • 2020-01-30
    • 2019-05-24
    • 2016-07-23
    • 2021-10-09
    • 2020-07-17
    • 2014-07-21
    • 2015-08-08
    • 2018-03-12
    相关资源
    最近更新 更多