78

考虑:

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.
    }
}

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

4

3 回答 3

108

这应该有效:

if (ptr->IsChildOne())
{
    SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
于 2011-07-22T20:22:26.140 回答
45

is的shared_ptr等价物和 is的等价物。static_caststatic_pointer_castshared_ptrdynamic_castdynamic_pointer_cast

于 2011-07-22T20:26:53.113 回答
27

从 C++11 开始,C++ 标准的 §20.10.2.2.9 ( [util.smartptr.shared.cast]static_cast ) 指定,const_castdynamic_castfor的等价物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>则返回空,否则返回与where和w共享所有权的指针。rw.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具有与 相似的要求和语义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())格式良好并具有明确定义的语义。如果dynamic_cast<T *>(r.get())是非零值,则返回与where和w共享所有权的指针,否则返回空值。rw.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为支持数组。

于 2016-04-28T11:02:49.403 回答