【问题标题】:up-casting std::shared_ptr using std::dynamic_pointer_cast使用 std::dynamic_pointer_cast 向上转换 std::shared_ptr
【发布时间】:2013-02-14 14:57:55
【问题描述】:

我开始在 C++0X/11 中使用智能指针,但遇到了一种特殊情况。 我想使用 shared_ptr 向上转换一个对象的实例。

Extend 类继承自 Base 类,其中 Base 类具有一个虚拟析构函数以使其具有多态性(否则 dynamic_pointer_cast 会抱怨非多态类转换)。

如果因此:

std::shared_ptr<Base> obj = std::make_shared<Base>();

然后我做:

obj = std::dynamic_pointer_cast<Extend>(obj);
  1. 安全吗?
  2. 指向该对象的其他指针会发生什么情况?是不是只有obj把它当成Extend,而其他共享指针还是把它当成Base?
  3. 向上转换同一个实例是否安全,或者我应该执行其他操作吗?

编辑:感谢您的回答。我问这个问题的真正原因是使用 SAX 解析器处理 XML 文档,但我被向上/向下转换迷惑了。 我想要的是:

std::shared_ptr<Extend> ex = std::dynamic_pointer_cast<Extend>(obj);
obj = ex;

但这一点意义都没有,我只会使用对象工厂。

【问题讨论】:

  • 给定 B 类 {}; class D : B {} 从 B* 到 D* 的转换是 down 转换,而从 D* 到 B* 的转换是 up 转换。我觉得你有相反的方向。

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


【解决方案1】:

这不是向上转换,而是向下转换(您正在从较少的类转换为更多的派生类)。然而:

安全吗?

是的,它是安全的,但是由于您试图向下转换指向运行时类型不是 Extend 的对象的指针,因此您将得到一个空指针作为回报。

指向该对象的其他指针会发生什么?是不是只有obj把它当成Extend,而其他共享指针还是把它当成Base?

您在这里有一个误解:向下转换指向对象的指针不会转换对象。如果对象不是目标类型,您将不会得到指向它的向下转换的指针。指向对象的类型(any 对象)在编译时确定并且不会改变。

向上转换同一个实例是否安全,或者我应该做其他事情吗?

不确定你的意思,这个问题的提法可能源于上述误解。但是,这条指令:

obj = std::dynamic_pointer_cast<Extend>(obj);

将使obj 成为空指针。赋值本身是合法的,因为您可以将指向派生类的(智能)指针分配给指向基类的(智能)指针。但是,由于赋值右侧的计算结果是一个空指针(因为上面写的),你最终会得到一个分配给obj 的空指针。

由于你基本上只是在重置obj,如果obj是最后一个指向通过make_shared&lt;&gt;()创建的对象的共享指针,那么在执行上述赋值后这个对象将被销毁。

【讨论】:

  • 是的,当然,我刚刚意识到我走错了路。谢谢你。我一直在尝试做的是将类成员从基础向上转换为扩展。
  • 最后一个问题肯定是关于类型转换obj,然后将结果存储回同一个obj 变量中。
  • @RobKennedy:我明白了,谢谢你的澄清。我编辑了我的答案。
【解决方案2】:

如果底层对象确实属于该类型,则只能向下转换为超类型。强制转换不能突然为你的底层对象赋予新的属性。

std::make_shared<Base>();

Will,在幕后致电:new Base

这意味着你不能:

obj = std::dynamic_pointer_cast<Extend>(obj);

你可以在new Base 上使用dynamic_cast 来使它变成它不是的东西。您需要make_shared&lt;Extend&gt;,然后使用shared_ptr&lt;Base&gt; 传递它。

【讨论】:

  • 是的,当我尝试从类扩展中调用方法时,我发现了这一点。有趣的是,编译器并没有抱怨我向上转换的那一行。所以向上转换 std::shared_ptr 是不可能的?
  • 不,这不是不可能的,但是如果底层对象确实属于该类型,则只能向下转换为超类型。强制转换不能突然为你的底层对象赋予新的属性。
猜你喜欢
  • 1970-01-01
  • 2019-10-20
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
相关资源
最近更新 更多