将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的“ 回归基础” 。
虽然Base
和Derived
是协变的,并且对它们的原始指针会相应地执行,但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_ptr
types不能协变,所以当返回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
,编译器无法看到一个类是从另一个类派生的。