【问题标题】:How to cast a shared_ptr<A> to shared_ptr<B> where B is derived from A?如何将 shared_ptr<A> 转换为 shared_ptr<B>,其中 B 派生自 A?
【发布时间】:2015-07-05 06:29:35
【问题描述】:

我有一个 std::list 容器,其中包含 A 类的共享指针。 我有另一个类,比如 B,它是从 A 派生的。

我目前有这样的代码来填充容器:

shared_ptr<B> b = shared_ptr<B>(new B);
container.push_back(b)

这很好用。

问题是,我怎样才能找回最初被推回容器的 shared_ptr ?

执行以下操作

   list<shared_ptr<A> >::iter anIter = myContainer.begin();
   shared_ptr<B> aB = *(anIter);

不要编译。我得到错误

Cannot convert 'A * const' to 'B *'

有什么建议吗?

【问题讨论】:

标签: c++ inheritance shared-ptr


【解决方案1】:

如果您知道自己确实检索到了 B,正如您的问题所暗示的,那么您可以使用 static_pointer_cast&lt;&gt;()

    shared_ptr<B> b = shared_ptr<B>(new B);
    container.push_back(b);
    auto it = container.begin();
    shared_ptr<B> aB = static_pointer_cast<B>(*it);
    aB->showb();

如有疑问,您可以使用 dynamic_pointer_cast&lt;&gt;()。但与传统的 dynamic_cast&lt;&gt;() 一样,这只有在你的类是多态的情况下才有效,即你有**至少一个虚函数:

   container.push_back(make_shared<A>());
   for (auto i = container.begin(); i!=container.end(); i++) {
       shared_ptr<B> spb = dynamic_pointer_cast<B>(*i); 
       if (spb)
           spb->showb();  // at least one virtual function 
       else cout << "the pointer was not to a B"; 
   }

普通指针的原理与static_cast&lt;&gt;()dynamic_cast&lt;&gt;()类似,见dynamic_cast and static_cast in C++。顺便说一句,还有一个const_pointer_cast&lt;&gt;(),就像普通指针的const_cast&lt;&gt;()

这里是live demo

【讨论】:

  • 多态行为呢?这必须是动态转换
  • 如果您 100% 确定对象是 B,请使用 static_pointer_cast,如果您不确定,请使用 dynamic_pointer_cast
  • 这个答案真的应该讲dynamic_pointer_cast并解释两者之间的区别
  • @Amxx 很难在不到 3 分钟的时间内完成一次完整的曝光。这个问题指的是 OP 说他用 B 填充并想要检索他的 B​​ 的示例。在这种情况下 static_poitner_cast 是合适的。尽管如此,我还是会完成。
  • @Christophe 在 OP 的情况下是肯定的……但这是建立具有长期价值的完整答案的好时机……这正是 SE 所寻找的。在以正确的方式教授事物的同时获得声誉的机会:)
【解决方案2】:

您可以使用std::dynamic_pointer_cast

你可以这样使用它:

std::shared_ptr<Base> basePtr;
std::shared_ptr<Derived> derivedPtr = std::dynamic_pointer_cast<Derived>(basePtr);

【讨论】:

  • 感谢您的建议。但这不会创建具有“初始”使用计数的共享指针,因为传入了原始 basePtr 吗?还是我错过了什么?
  • @TotteKarlsson basePtr 应该是shared_ptr。我会将其添加到答案中。
  • 感谢您的回答!我选择了这个答案,因为它直截了当!
猜你喜欢
  • 2017-12-24
  • 2011-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
  • 2012-09-03
  • 2013-07-02
相关资源
最近更新 更多