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_ptrof a derived type to a function that takes a shared_ptrof a base type?
将shared_ptr派生类型的 a传递给采用shared_ptr基类型的a 的函数的最佳方法是什么?
I generally pass shared_ptrs 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_castseems a bit excessive for a simple derived-to-base cast. - As I understand it,
dynamic_pointer_castcreates 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_ptrby value, e.g.int foo(unique_ptr<bar> b). Callers shouldstd::movethe value into the function.Functions that extend the lifetime of an object should take a
shared_ptrby 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 Baseand Derivedare covariant and raw pointers to them will act accordingly, shared_ptr<Base>and shared_ptr<Derived>are notcovariant. The dynamic_pointer_castis the correct and simplest way to handle this problem.
虽然Base与Derived是协变的和原始指针他们会采取相应的行动,shared_ptr<Base>并且shared_ptr<Derived>是不是协变的。这dynamic_pointer_cast是处理这个问题的正确和最简单的方法。
(Edit:static_pointer_castwould 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_ptrwhen passing it to foo().
但是,如果您的foo()函数不希望参与延长生命周期(或者,更确切地说,参与对象的共享所有权),那么最好在将其传递给 时接受 aconst Base&并取消引用。shared_ptrfoo()
void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);
As an aside, because shared_ptrtypes 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_ptris 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 #includeof 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 #includethe compiler could not see that one class was derived from the other.
我有这个问题。该std::shared<derived>不会投给std::shared<base>。我已经提前声明了两个类,以便我可以保存指向它们的指针,但是因为我没有#include编译器,所以无法看到一个类是从另一个类派生的。

