C++ 如何向下转换 std::shared_ptr ?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6795629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:41:31  来源:igfitidea点击:

How does one downcast a std::shared_ptr?

c++c++11shared-ptrdowncast

提问by Billy ONeal

Consider:

考虑:

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

(Note that I can't simply do a std::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get())), because then the reference counts don't get shared between the two shared_ptrs)

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

回答by mwigdahl

This ought to work:

这应该有效:

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

回答by Joel

The shared_ptrequivalent of static_castis static_pointer_cast, and the shared_ptrequivalent of dynamic_castis dynamic_pointer_cast.

shared_ptr当量static_caststatic_pointer_cast,与shared_ptr等效的dynamic_castdynamic_pointer_cast

回答by jotik

Starting from C++11, §20.10.2.2.9 ([util.smartptr.shared.cast]) of the C++ standard specifies the equivalents of static_cast, const_castand dynamic_castfor std::shared_ptrto be as follows:

从 C++11 开始,C++ 标准的 §20.10.2.2.9 ( [util.smartptr.shared.cast]) 指定static_cast,const_castdynamic_castfor的等效项std::shared_ptr如下:

std::static_pointer_cast:

std::static_pointer_cast

template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;

static_pointer_castrequires static_cast<T *>(r.get())to be well formed. If ris empty, an empty shared_ptr<T>is returned, otherwise returns a pointer wsharing ownership with rwhere w.get() == static_cast<T *>(r.get())and w.use_count() == r.use_count().

static_pointer_cast需要static_cast<T *>(r.get())很好地形成。如果r为空,shared_ptr<T>则返回空,否则返回wrwherew.get() == static_cast<T *>(r.get())和共享所有权的指针w.use_count() == r.use_count()

std::const_pointer_cast:

std::const_pointer_cast

template <class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;

const_pointer_casthas similar requirements and semantics to static_pointer_cast, except that const_castis used instead of static_cast.

const_pointer_cast与 具有相似的要求和语义static_pointer_cast,除了const_cast使用 代替static_cast

std::dynamic_pointer_cast:

std::dynamic_pointer_cast

template <class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;

dynamic_pointer_castis a bit different as it requires dynamic_cast<T *>(r.get())to be well formed and have well defined semantics. If dynamic_cast<T *>(r.get())is a non-zero value, returns a pointer wsharing ownership with rwhere w.get() == dynamic_cast<T *>(r.get())and w.use_count() == r.use_count(), otherwise an empty shared_ptr<T>is returned.

dynamic_pointer_cast有点不同,因为它需要dynamic_cast<T *>(r.get())格式良好并具有明确定义的语义。如果dynamic_cast<T *>(r.get())是非零值,则返回wrwherew.get() == dynamic_cast<T *>(r.get())和共享所有权的指针w.use_count() == r.use_count(),否则shared_ptr<T>返回空值。

std::reinterpret_pointer_cast:

std::reinterpret_pointer_cast

For C++17, N3920(adopted into Library Fundamentals TS in February 2014) also proposed a std::reinterpret_pointer_castsimilar to the above, which would only require reinterpret_cast<T *>((U *) 0)to be well formed and returns shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get())). Note N3920 also changed the wording for the other shared_ptrcasts and extended shared_ptrto support arrays.

对于 C++17,N39202014 年 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为支持数组。