传递shared_ptr< Derived> as shared_ptr< Base> [英] Passing shared_ptr<Derived> as shared_ptr<Base>

查看:163
本文介绍了传递shared_ptr< Derived> as shared_ptr< Base>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将派生类型的 shared_ptr 传递给需要 shared_ptr



我通常通过引用 shared_ptr 来避免不必要的副本:

  int foo(const shared_ptr< bar>& ptr); 

但这不起作用,如果我尝试做

  int foo(const shared_ptr< Base>& ptr); 

...

shared_ptr< Derived> bar = make_shared< Derived>();
foo(bar);

我可以使用

  foo(dynamic_pointer_cast< Base,Derived>(bar)); 

但这看起来并不理想,有两个原因:





  • 对于简单的派生至基地演员来说, dynamic_cast >根据我的理解, dynamic_pointer_cast 创建一个指针的副本(虽然是临时的)传递给函数。



有更好的解决方案吗?



更新后代:



原来是一个缺少头文件的问题。此外,我在这里想做的是一个反模式。一般来说,




  • 不影响对象生命周期的函数(即对象在函数持续时间内保持有效)取一个简单的引用或指针,例如 int foo(bar& b)


  • 对象(即是给定对象的最终用户)应该通过值取一个 unique_ptr ,例如 int foo(unique_ptr< bar> b)。调用者应该 std :: move 将值插入函数。


  • 对象应该通过值取一个 shared_ptr ,例如 int foo(shared_ptr< bar> b)。通常建议避免循环引用




查看Herb Sutter的返回基本讲座。 c> c> c> $ c> Derived 是协变的,并且指向它们的原始指针将相应地动作, shared_ptr shared_ptr 协变。 dynamic_pointer_cast 是处理此问题的正确和最简单的方法。



编辑: static_pointer_cast 会更合适,因为你是从派生类型转换为基本类型,这是安全的,不需要运行时检查。)



但是,如果你的 foo()函数不希望参与延长生命周期对象的共享所有权),那么它最好接受 const Base& ,并在传递它时解除引用 shared_ptr foo()

  void foo(const Base& base) ; 
[...]
shared_ptr< Derived> spDerived = getDerived();
foo(* spDerived);

另外,因为 shared_ptr 是协变的,当返回 shared_ptr 的类型时,协变返回类型的隐式转换规则不适用。


What is the best method to go about passing a shared_ptr of a derived type to a function that takes a shared_ptr of a base type?

I generally pass shared_ptrs by reference to avoid a needless copy:

int foo(const shared_ptr<bar>& ptr);

but this doesn't work if I try to do something like

int foo(const shared_ptr<Base>& ptr);

...

shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);

I could use

foo(dynamic_pointer_cast<Base, Derived>(bar));

but this seems sub-optimal for two reasons:

  • A dynamic_cast seems a bit excessive for a simple derived-to-base cast.
  • As I understand it, dynamic_pointer_cast creates a copy (albeit a temporary one) of the pointer to pass to the function.

Is there a better solution?

Update for posterity:

It turned out to be an issue of a missing header file. Also, what I was trying to do here is considered an antipattern. Generally,

  • Functions that don't impact an object's lifetime (i.e. the object remains valid for the duration of the function) should take a plain reference or pointer, e.g. int foo(bar& b).

  • Functions that consume an object (i.e. are the final users of a given object) should take a unique_ptr by value, e.g. int foo(unique_ptr<bar> b). Callers should std::move the value into the function.

  • Functions that extend the lifetime of an object should take a shared_ptr by value, e.g. int foo(shared_ptr<bar> b). The usual advice to avoid circular references applies.

See Herb Sutter's Back to Basics talk for details.

解决方案

Although Base and Derived are covariant and raw pointers to them will act accordingly, shared_ptr<Base> and shared_ptr<Derived> are not covariant. The dynamic_pointer_cast is the correct and simplest way to handle this problem.

(Edit: static_pointer_cast would be more appropriate because you're casting from derived to base, which is safe and doesn't require runtime checks. See comments below.)

However, if your foo() function doesn't wish to take part in extending the lifetime (or, rather, take part in the shared ownership of the object), then its best to accept a const Base& and dereference the shared_ptr when passing it to foo().

void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);

As an aside, because shared_ptr types cannot be covariant, the rules of implicit conversions across covariant return types does not apply when returning types of shared_ptr<T>.

这篇关于传递shared_ptr&lt; Derived&gt; as shared_ptr&lt; Base&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆