使用std :: dynamic_pointer_cast上传std :: shared_ptr

时间:2013-02-14 14:57:56

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

我开始使用C ++ 0X / 11中的智能指针,我遇到了一种奇怪的情况。 我想使用shared_ptr来构建对象的实例。

Class 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. 向上播放同一个实例是否安全?或者我应该做其他事情吗?
  4. 编辑:谢谢你的回答。我问这个问题的真正原因是处理XML文档使用SAX解析器,但是我得到了上升/下降的信息。 我有点想要的是:

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

    但它完全没有意义,相反我只会使用一个对象工厂。

2 个答案:

答案 0 :(得分:10)

这不是一个上传,而是一个向下投射(你从一个较少的类投射到一个更多的派生类)。但是:

  

安全吗?

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

  

对象的其他指针会发生什么?只有obj将它视为Extend,而其他共享指针仍将它视为Base?

你有一个误解:向下转换指向对象的指针不会转换对象。如果对象不是目标类型,则不会获得指向它的下行指针。指向对象的类型(任何对象)的类型在编译时确定,不会更改。

  

向上播放同一个实例是否安全,还是应该做其他事情?

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

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

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

由于您基本上只是重置obj,如果obj是通过make_shared<>()创建的对象的最后一个共享指针,则在执行上述赋值后,此对象将被销毁。 / p>

答案 1 :(得分:6)

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

std::make_shared<Base>();

将在封底下致电:new Base

这意味着你不能:

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

您可以使用dynamic_cast上的new Base将其变为某些内容。您需要make_shared<Extend>,然后使用shared_ptr<Base>传递它。