我开始使用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);
std::shared_ptr<Extend> ex = std::dynamic_pointer_cast<Extend>(obj);
obj = ex;
但它完全没有意义,相反我只会使用一个对象工厂。
答案 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>
传递它。