如何降低一个std :: shared_ptr?
考虑:
struct SomethingThatsABase { virtual bool IsChildOne() const { return false; } virtual bool IsChildTwo() const { return false; } }; struct ChildOne : public SomethingThatsABase { virtual bool IsChildOne() const { return true; } }; struct ChildTwo : public SomethingThatsABase { virtual bool IsChildTwo() const { return true; } }; void SomeClientExpectingAChildOne(std::shared_ptr<ChildOne> const& ptrOne) { //Does stuff } void SomeClient(std::shared_ptr<SomethingThatsABase> const& ptr) { if (ptr->IsChildOne()) { SomeClientExpectingAChildOne(ptr); //Oops. //Hmm.. can't static_cast here, because we need a `shared_ptr` out of it. } }
(请注意,我不能简单地执行std::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get()))
,因为那么引用计数不会在两个shared_ptr
之间共享)
这应该工作:
if (ptr->IsChildOne()) { SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr)); }
static_cast
的shared_ptr
相当于static_pointer_cast
,而dynamic_cast
的shared_ptr
相当于dynamic_pointer_cast
。
从C ++ 11开始,C ++标准的§20.10.2.2.9( [util.smartptr.shared.cast] )为std::shared_ptr
指定了static_cast
, const_cast
和dynamic_cast
的等价物,如下所示:
std::static_pointer_cast
:
template <class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
static_pointer_cast
要求static_cast<T *>(r.get())
格式良好。 如果r
为空,则返回一个空的shared_ptr<T>
,否则返回一个与r
共享所有权的指针,其中w.get() == static_cast<T *>(r.get())
和w.use_count() == r.use_count()
。
std::const_pointer_cast
:
template <class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
const_pointer_cast
与const_pointer_cast
具有相似的需求和语义,只是使用了const_cast
而不是static_cast
。
std::dynamic_pointer_cast
:
template <class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
dynamic_pointer_cast
有点不同,因为它需要dynamic_cast<T *>(r.get())
格式良好并具有明确定义的语义。 如果dynamic_cast<T *>(r.get())
是一个非零值,则返回一个与r
共享所有权的指针,其中w.get() == dynamic_cast<T *>(r.get())
和w.use_count() == r.use_count()
,否则返回一个空的shared_ptr<T>
。
std::reinterpret_pointer_cast
:
对于C ++ 17, N3920 ( 2014年2月采用的库基础TS)也提出了类似于上述的std::reinterpret_pointer_cast
,它只需要reinterpret_cast<T *>((U *) 0)
返回shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get()))
。 注意N3920也改变了其他shared_ptr
转换和扩展shared_ptr
支持数组的语句。