派生类的 unique_ptr 作为将 unique_ptr 传递给基类的函数的参数

问题描述 投票:0回答:4

我正在尝试在将

unique_ptr
带到基类的函数中使用
unique_ptr
到派生类。像这样的东西:

class Base {};

class Derived : public Base {};

void f(unique_ptr<Base> const &base) {}

…

unique_ptr<Derived> derived = unique_ptr<Derived>(new Derived);
f(derived);

如果我正确理解这个答案,这段代码应该可以工作,但它会导致以下编译错误:

error C2664: 'f': 无法将参数 1 从 'std::unique_ptr<_Ty>' 转换为 'const std::unique_ptr<_Ty> &'

IntelliSense:不存在从“std::unique_ptr>”到“const std::unique_ptr>”的合适的用户定义转换

如果我把

f
改成
unique_ptr<Derived> const &derived
,效果很好,但这不是我想要的。

我做错了什么吗?我该怎么做才能解决这个问题?

我正在使用 Visual Studio 2012.

c++ visual-studio-2012 c++11 unique-ptr
4个回答
105
投票

你有三个选择:

  1. 放弃所有权。这将使您的局部变量在函数调用后无法访问动态对象;对象已经转移给被调用者:

    f(std::move(derived));
    
  2. 更改

    f
    的签名:

    void f(std::unique_ptr<Derived> const &);
    
  3. 更改变量的类型:

    std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived);
    

    或者当然只是:

    std::unique_ptr<base> derived(new Derived);
    

    甚至:

    std::unique_ptr<base> derived = std::make_unique<Derived>();
    
  4. 更新: 或者,按照评论中的建议,根本不要转让所有权:

    void f(Base & b);
    
    f(*derived);
    

47
投票

我有已接受答案的选项#1,但我仍然遇到相同的编译错误。我用头撞墙一个多小时,我终于意识到我有

class Derived : Base {};

代替

class Derived : public Base {};

13
投票

一个可能的解决方案是将参数的类型更改为

Base const*
,并传递
derived.get()
unique_ptr const<Base>&
没有所有权转移(并且
unique_ptr
没有被修改),因此更改为
Base const*
不会改变含义。


Herb Sutter 在 Smart Pointer Parameters 中详细讨论了传递智能指针参数。链接文章的摘录提到了这种确切情况:

传递

const unique_ptr<widget>&
很奇怪,因为它只能接受
null
widget
的生命周期恰好在调用代码中通过
unique_ptr
进行管理,而被调用者通常不应该关心调用者的生命周期管理选择。通过
widget*
涵盖了这些情况的严格超集,并且可以接受“
null
widget
”,而不管调用者恰好使用的生命周期策略。


-1
投票

另一种方法是更改

f
的签名并以稍微不同的方式使用它:

void f(Base* base_ptr) {
    // take ownership inside the function
    std::unique_ptr<Base> base {base_ptr};
    // ...
}

// ...
auto derived = std::make_unique<Derived>();
f(derived.release());  // release ownership
© www.soinside.com 2019 - 2024. All rights reserved.