【问题标题】:Why is casting on shared_ptr like this?为什么要像这样在 shared_ptr 上进行投射?
【发布时间】:2020-06-04 13:54:54
【问题描述】:

我看过一篇关于该主题的旧帖子。由于我的新帐户和缺乏声誉点,我无法在那里发表评论;因此,我正在发这篇文章。

我过去一直在寻找一种将共享指针从一种类型转换为另一种类型(从基类到派生类)的方法,以便访问派生端的一些私有成员。我知道最好避免向下转换,但这是框架......无论如何,我在原帖上看到的答案是:

std::shared_ptr<A> ap = ...;
dynamic_cast<B&>(*ap).b_function();
if (B* bp = dynamic_cast<B*>(ap.get()) 

现在,在命令中:dynamic_cast&lt;B&amp;&gt;(*ap).b_function() 我知道这里的取消引用符号为我们提供了对 shared_ptr 指向对象的引用。我的问题是为什么我们需要 B 的参考(即 B&)?我们不能让它像这样工作吗:

B& Bref = dynamic_cast<B>(*ap);
Bref.b_function();

我对模板不是很熟悉(比如 shared_ptr 是实现的),所以我猜是我对这件事缺乏了解。有人可以向我解释 & 在这种情况下的含义以及为什么我给出的替代方案不起作用?

【问题讨论】:

  • 看起来代码设计不正确。通常dynamic_cast 是一个错误,因为您应该只完成一个接口,而不是扩展它。当您扩展接口(派生类添加新功能)时,您必须这样做,因为父类对这些新功能一无所知。
  • 听起来你可能正在寻找dynamic_pointer_cast
  • 原因可能不会让你满意,但这仅仅是因为标准是这样定义的。也许是因为它更明确,也许是因为它匹配 B* 版本,也许是因为它更安全(B 没有那么明确)。它也与static_cast等其他演员表更加一致。
  • 从技术上讲,您不必拥有&amp;,但在这种情况下,代码将转换为对B 实例的引用,或者:B&amp;。否则,您将复制*ap
  • 您可以动态转换指针或引用。动态转换值是不可能的。

标签: c++ casting shared-ptr


【解决方案1】:

关键是转换为非指针/引用类型始终是 C++ 中的转换。您得到与原始值不同的转换值。它是一个新的本地对象,在内存中有自己的位置。因此,对此副本的任何更改都不会影响原始值。

对于AB 类,转换(B)a 将通过调用B::B(A&amp;)B 的构造函数来构造新对象。


当然,dynamic_cast&lt;&gt; 不应该用于此类转换,因此标准禁止使用非指针/引用类型的 dynamic_cast&lt;&gt;

【讨论】:

  • 谢谢。由于某种原因,我完全忘记了这种情况(基本上是转换和创建副本)。对我来说还是一大早。非常感谢您的回复。
【解决方案2】:

我的问题是为什么我们需要B(即B&amp;)的引用?我们不能让它像这样工作吗:

B& Bref = dynamic_cast<B>(*ap);
Bref.b_function();

不,你不能这样做。引用 C++ Stadnard [expr.dynamic.cast/1]:

表达式dynamic_­cast&lt;T&gt;(v) 的结果是将表达式v 转换为类型T 的结果。 T 应为指向完整类类型的指针或引用,或“指向 cv void 的指针”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多