传递 shared_ptr<Derived>作为 shared_ptr<Base>
将派生类型的 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?
我通常通过引用传递 shared_ptr
以避免不必要的复制:
I generally pass shared_ptr
s 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);
我可以使用
foo(dynamic_pointer_cast<Base, Derived>(bar));
但这似乎不是最理想的,原因有两个:
but this seems sub-optimal for two reasons:
- 一个
dynamic_cast
对于一个简单的派生到基础的转换来说似乎有点过分. - 据我所知,
dynamic_pointer_cast
创建要传递给函数的指针的副本(尽管是临时副本).
- 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.
有更好的解决方案吗?
原来是缺少头文件的问题.此外,我在这里尝试做的事情被认为是一种反模式.一般来说,
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,
不影响对象生命周期的函数(即对象在函数的持续时间内保持有效)应该采用普通引用或指针,例如
int foo(bar& b)
.
消费一个对象(即给定对象的最终用户)的函数应该采用一个 unique_ptr
按值,例如int foo(unique_ptr
.调用者应该将值std::move
放入函数中.
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.
延长对象生命周期的函数应该采用 shared_ptr
值,例如int foo(shared_ptr
.避免循环引用的通常建议适用.
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.
有关详细信息,请参阅 Herb Sutter 的回归基础讲座.
See Herb Sutter's Back to Basics talk for details.
推荐答案
虽然 Base
和 Derived
是协变的并且指向它们的原始指针会相应地起作用,shared_ptr<Base>
和 shared_ptr
是非协变的.dynamic_pointer_cast
是处理此问题的正确且最简单的方法.
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.
( static_pointer_cast
会更合适,因为您是从派生转换到基类,这是安全的,不需要运行时检查.请参阅下面的评论.)
( 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.)
然而,如果你的 foo()
函数不想参与延长生命周期(或者,更确切地说,参与对象的共享所有权),那么最好接受一个 const Base&
并在将 shared_ptr
传递给 foo()
时取消引用它.
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);
顺便说一句,因为 shared_ptr
类型不能协变,当返回 shared_ptr
类型时,跨协变返回类型的隐式转换规则不适用.
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>
.
相关文章