如何将一个std :: shared_ptr投降?

Bil*_*eal 62 c++ shared-ptr downcast c++11

考虑:

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

(注意,我不能简单地做一个std::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get())),因为那时引用计数不会在两者之间共享shared_ptr)

mwi*_*ahl 90

这应该工作:

if (ptr->IsChildOne())
{
    SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
Run Code Online (Sandbox Code Playgroud)

  • @Frerich:`shared_ptr`有两个指针 - 一个指向共享对象,另一个指向具有强引用和弱引用计数的块.两个不同类型的`shared_ptr`可以毫无困难地共享强弱引用计数块.我的猜测是它使用`static_pointer_cast`作为`shared_ptr`的`朋友'来实现,但当然你的实现可能会有所不同. (4认同)
  • +1 - 我不知道`std :: static_pointer_cast`!这是如何工作的,返回的`shared_ptr`是否像代理一样,以便两个共享指针保持相同的引用计数? (3认同)
  • 我总是在Boost中使用`shared_dynamic_cast`.显然,`dynamic_pointer_cast`更通用,因为它适用于各种不同类型的指针(`shared_ptr`,原始指针,`intrusive_ptr`,以及未来可能的其他任何东西). (2认同)

Joe*_*oel 34

shared_ptr当量static_caststatic_pointer_cast,与shared_ptr等效dynamic_castdynamic_pointer_cast.


jot*_*tik 20

从C++ 11开始,§20.10.2.2.9([util.smartptr.shared.cast] )的C++标准的规定的等效物static_cast,const_cast以及dynamic_cast用于std::shared_ptr为如下:

std::static_pointer_cast:

template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
Run Code Online (Sandbox Code Playgroud)

static_pointer_cast要求static_cast<T *>(r.get())形成良好.如果r为空,shared_ptr<T>则返回空,否则返回wrwhere 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;
Run Code Online (Sandbox Code Playgroud)

const_pointer_cast具有类似的要求和语义static_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;
Run Code Online (Sandbox Code Playgroud)

dynamic_pointer_cast有点不同,因为它需要dynamic_cast<T *>(r.get())良好的形成并具有良好定义的语义.如果dynamic_cast<T *>(r.get())是一个非零值,返回一个指针w与共享所有权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月采用的Library Fundamentals 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为支持数组.