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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:15:34  来源:igfitidea点击:

Passing shared_ptr<Derived> as shared_ptr<Base>

c++castingc++11shared-ptrsmart-pointers

提问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 should std::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.

虽然BaseDerived是协变的和原始指针他们会采取相应的行动,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编译器,所以无法看到一个类是从另一个类派生的。