将shared_ptr <Derived>作为shared_ptr <Base>传递

将派生types的shared_ptr传递给带有基types的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创build一个副本(尽pipe是临时的)传递给函数的指针。

有更好的解决scheme吗?

后人更新:

原来是一个缺less头文件的问题。 另外,我在这里试图做的是被认为是反模式。 通常,

  • 不影响对象的生命周期(即对象在函数期间保持有效的函数)的函数应该使用一个普通的引用或指针,例如int foo(bar& b)

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

  • 延长对象生命周期的函数应该通过值来获取shared_ptr ,例如int foo(shared_ptr<bar> b) 。 避免循环引用的通常build议适用。

详情请参阅Herb Sutter的“ 回归基础” 。

虽然BaseDerived是协变的,并且对它们的原始指针会相应地执行,但shared_ptr<Base>shared_ptr<Derived> 不是协变的。 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_ptrtypes不能协变,所以当返回shared_ptr<T>types时,协变返回types的隐式转换规则不适用。

听起来你太努力了 shared_ptr便宜,可以复制; 这是它的目标之一。 通过引用来传递它们并不是很成功。 如果你不想共享,传递原始指针。

也就是说,有两种方法可以做到这一点,我可以从头顶上想到:

 foo(shared_ptr<Base>(bar)); foo(static_pointer_cast<Base>(bar)); 

同时检查包含派生类的完整声明的头文件的#include是否在源文件中。

我有这个问题。 std::shared<derived>不会转换成std::shared<base> 。 我已经向前宣布了两个类,以便我可以指向它们,但是因为我没有#include ,编译器无法看到一个类是从另一个类派生的。