C++ 将 shared_ptr<Derived> 作为 shared_ptr<Base> 传递
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13403490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing shared_ptr<Derived> as shared_ptr<Base>
提问by Matt Kline
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
派生类型的 a传递给采用shared_ptr
基类型的a 的函数的最佳方法是什么?
I generally pass shared_ptr
s by reference to avoid a needless copy:
我通常通过shared_ptr
引用传递s 以避免不必要的副本:
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.
dynamic_cast
对于简单的派生到基类转换,A似乎有点过分。- 据我了解,
dynamic_pointer_cast
创建要传递给函数的指针的副本(尽管是临时副本)。
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 consumean 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 shouldstd::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 referencesapplies.
不影响对象生命周期的函数(即对象在函数的持续时间内保持有效)应该采用普通引用或指针,例如
int foo(bar& b)
.使用对象的函数(即是给定对象的最终用户)应该采用
unique_ptr
按值,例如int foo(unique_ptr<bar> b)
。std::move
调用者应该将值放入函数中。延长对象生命周期的函数应该采用
shared_ptr
按值,例如int foo(shared_ptr<bar> b)
。避免循环引用的通常建议适用。
See Herb Sutter's Back to Basics talkfor details.
有关详细信息,请参阅 Herb Sutter 的“回归基础”演讲。
采纳答案by Bret Kuhns
Although Base
and Derived
are covariant and raw pointers to them will act accordingly, shared_ptr<Base>
and shared_ptr<Derived>
are notcovariant. The dynamic_pointer_cast
is the correct and simplest way to handle this problem.
虽然Base
与Derived
是协变的和原始指针他们会采取相应的行动,shared_ptr<Base>
并且shared_ptr<Derived>
是不是协变的。这dynamic_pointer_cast
是处理这个问题的正确和最简单的方法。
(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.)
(编辑:static_pointer_cast
会更合适,因为您是从派生转换为基类,这是安全的,不需要运行时检查。请参阅下面的评论。)
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()
.
但是,如果您的foo()
函数不希望参与延长生命周期(或者,更确切地说,参与对象的共享所有权),那么最好在将其传递给 时接受 aconst Base&
并取消引用。shared_ptr
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
类型不能协变,所以当返回shared_ptr<T>
.
回答by dshepherd
This will also happen if you've forgotten to specify publicinheritance on the derived class, i.e. if like me you write this:
如果您忘记在派生类上指定公共继承,也会发生这种情况,即,如果您像我一样这样写:
class Derived : Base
{
};
回答by Pete Becker
Sounds like you're trying too hard. shared_ptr
is cheap to copy; that's one of its goals. Passing them around by reference doesn't really accomplish much. If you don't want sharing, pass the raw pointer.
听起来你太努力了。shared_ptr
复制便宜;这是它的目标之一。通过引用传递它们并没有真正完成多少。如果您不想共享,请传递原始指针。
That said, there are two ways to do this that I can think of off the top of my head:
也就是说,有两种方法可以做到这一点,我可以立即想到:
foo(shared_ptr<Base>(bar));
foo(static_pointer_cast<Base>(bar));
回答by Phil Rosenberg
Also check that the #include
of the header file containing the full declaration of the derived class is in your source file.
还要检查#include
包含派生类完整声明的头文件是否在源文件中。
I had this problem. The std::shared<derived>
would not cast to std::shared<base>
. I had forward declared both classes so that I could hold pointers to them, but because I didn't have the #include
the compiler could not see that one class was derived from the other.
我有这个问题。该std::shared<derived>
不会投给std::shared<base>
。我已经提前声明了两个类,以便我可以保存指向它们的指针,但是因为我没有#include
编译器,所以无法看到一个类是从另一个类派生的。