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

时间:2011-07-22 20:18:01

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

考虑:

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之间共享

3 个答案:

答案 0 :(得分:81)

这应该有效:

if (ptr->IsChildOne())
{
    SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}

答案 1 :(得分:34)

shared_ptr等效static_caststatic_pointer_cast,而shared_ptr等效dynamic_castdynamic_pointer_cast

答案 2 :(得分:19)

从C ++ 11开始,C ++标准的§20.10.2.2.9([util.smartptr.shared.cast])指定了static_castconst_castdynamic_cast的等价物{ {1}}如下:

std::shared_ptr

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>与[{1}}共享所有权wr。< / p>

w.get() == static_cast<T *>(r.get())

w.use_count() == r.use_count()

std::const_pointer_casttemplate <class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept; 具有相似的要求和语义,但使用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; 格式良好且具有明确定义的语义。如果dynamic_pointer_cast为非零值,则返回指针dynamic_cast<T *>(r.get())与[{1}}共享所有权dynamic_cast<T *>(r.get())w,否则为空r归还。

w.get() == dynamic_cast<T *>(r.get())

对于C ++ 17,N3920(已在图书馆基础知识TS in February 2014中采用)也提出了与上述类似的w.use_count() == r.use_count(),只需要shared_ptr<T>格式良好并返回std::reinterpret_pointer_cast。注意N3920还更改了其他std::reinterpret_pointer_cast强制转换和扩展reinterpret_cast<T *>((U *) 0)的措辞以支持数组。