【问题标题】:Downcasting from shared pointer of base class to reference of derived class从基类的共享指针向下转换为派生类的引用
【发布时间】:2020-03-16 00:36:15
【问题描述】:

我正在学习使用共享指针。

假设我们有两个类,BaseDerived(继承自 Base),没有多态性(没有虚方法,除了析构函数)和一个循环:

for (std::shared_ptr<Base>& pB : collection)
{
  <downcast>
  ...
}

就代码质量、良好实践、性能或任何其他原因而言,以下哪一项是最好的&lt;downcast&gt;

(1) Derived& d = static_cast<Derived&>(*pB);
(2) Derived& d = *(std::static_pointer_cast<Derived>(pB).get());

【问题讨论】:

  • 第一。 static_pointer_cast 仅用于制作该共享指针的副本,在这种情况下您不需要。
  • 如果您在 CRTP 中执行此操作,则两者都可以。否则,两者同样糟糕。
  • BaseDerived 进行“传统”继承:class Derived : public Base {...}

标签: c++ c++11 shared-ptr


【解决方案1】:

由于您的类不是多态的,因此您处于如履薄冰的状态,因为您无法检查向下转换在运行时是否有效。如果没有,您可能会以未定义的行为告终。静态转换如果没问题,但前提是您(超过)100% 确定所有迭代中的 pB 指向 Derived 类型的对象。

可能的最佳实践/最安全的解决方案是将虚拟析构函数添加到 Base 并使用动态转换:

Derived& d = dynamic_cast<Derived&>(*pB);

如果转换无效,这将引发异常。当然,由于向下转换有效性的运行时检查,此解决方案的效率会降低。

【讨论】:

  • 我强烈不同意您对 Arne J 回答的评论。他的回答绝对一个答案,而你的回答(虽然这是很好的额外评论)既没有明确表示“不要那样做”,也没有回答这个问题。我已经投票取消删除,如果取消删除,我会投票赞成。
  • @MartinBonnersupportsMonica 我重新访问了已删除的答案,你是对的,我的错(我有点期待更多关于性能、良好实践的推理......)。不幸的是,我不能投票取消删除它,但如果它发生,我会投票。感谢您指出这一点。
  • 我忘了提到Base 已经有一个虚拟析构函数。我不知道这是将类关系视为多态的充分条件
  • @MartinBonnersupportsMonica 有人可以重新发布 Arne J 答案的摘要吗?功劳确实会归于他;)
  • @Gupta:答案的全文是:“第一个。static_pointer_cast 仅用于制作共享指针的副本,在这种情况下您不需要”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
相关资源
最近更新 更多