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

Æle*_*lex 10 c++ shared-ptr upcasting c++11

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

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

如果:

std::shared_ptr<Base> obj = std::make_shared<Base>();
Run Code Online (Sandbox Code Playgroud)

然后我做:

obj = std::dynamic_pointer_cast<Extend>(obj);
Run Code Online (Sandbox Code Playgroud)
  1. 安全吗?
  2. 其他指向对象的指针会发生什么?只有obj将它视为Extend,而其他共享指针仍会将其视为Base吗?
  3. 上传同一个实例是否安全,还是应该做其他事情?

编辑:谢谢你的答案.我问这个问题的真正原因是处理XML文档使用SAX解析器,但是我得到了上升/下降的信息.我想要的是:

std::shared_ptr<Extend> ex = std::dynamic_pointer_cast<Extend>(obj);
obj = ex;
Run Code Online (Sandbox Code Playgroud)

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

And*_*owl 10

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

安全吗?

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

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

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

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

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

obj = std::dynamic_pointer_cast<Extend>(obj);
Run Code Online (Sandbox Code Playgroud)

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

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


Ben*_*enj 7

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

std::make_shared<Base>();
Run Code Online (Sandbox Code Playgroud)

将在封面下打电话:new Base.

这意味着你不能:

obj = std::dynamic_pointer_cast<Extend>(obj);
Run Code Online (Sandbox Code Playgroud)

任何超过你可以使用dynamic_cast一个new Base,使之成为东西,它不是.你需要make_shared<Extend>然后使用一个传递它shared_ptr<Base>.

  • 不,这不是没有问题,但是如果基础对象确实属于该类型,则只能将其转换为超级类型。强制转换不能突然赋予您的基础对象新的属性。 (2认同)