如何向下转换 std::shared_ptr?

发布于 2024-11-26 03:02:10 字数 912 浏览 1 评论 0 原文

考虑一下:(

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(static_cast(ptr.get())),因为这样引用计数就不会在两个 shared_ptr 之间共享)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

满天都是小星星 2024-12-03 03:02:10

这应该有效:

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

This ought to work:

if (ptr->IsChildOne())
{
    SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
小嗷兮 2024-12-03 03:02:10

static_castshared_ptr 等价物是 static_pointer_cast,而 dynamic_castshared_ptr 等价物是dynamic_pointer_cast

The shared_ptr equivalent of static_cast is static_pointer_cast, and the shared_ptr equivalent of dynamic_cast is dynamic_pointer_cast.

盗心人 2024-12-03 03:02:10

从 C++11 开始,§20.10.2.2.9 ([util.smartptr C++ 标准的 .shared.cast])指定了 static_castconst_castdynamic_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;

static_pointer_cast 需要 static_cast(r.get ()) 格式良好。如果 r 为空,则返回空的 shared_ptr,否则返回与 r 共享所有权的指针 w > 其中 w.get() == static_cast(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_caststatic_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(r.get()) 才能正常工作形成并具有明确定义的语义。如果 dynamic_cast(r.get()) 是非零值,则返回与 r 共享所有权的指针 w其中 w.get() ==dynamic_cast(r.get())w.use_count() == r.use_count(),否则一个空的返回shared_ptr

std::reinterpret_pointer_cast

对于 C++17,N3920 (于 2 月被采纳为图书馆基础知识 TS 2014)也提出了与上面类似的std::reinterpret_pointer_cast,只需要reinterpret_cast((U *) 0)格式良好并返回 shared_ptr(r, reinterpret_cast::element_type *>(r.get()))。注意 N3920 还更改了其他 shared_ptr 转换的措辞,并扩展了 shared_ptr 以支持数组。

Starting from C++11, §20.10.2.2.9 ([util.smartptr.shared.cast]) of the C++ standard specifies the equivalents of static_cast, const_cast and dynamic_cast for std::shared_ptr to be as follows:

std::static_pointer_cast:

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

static_pointer_cast requires static_cast<T *>(r.get()) to be well formed. If r is empty, an empty shared_ptr<T> is returned, otherwise returns a pointer w sharing ownership with r where w.get() == static_cast<T *>(r.get()) and 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 has similar requirements and semantics to static_pointer_cast, except that const_cast is used instead of 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 is 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 w sharing ownership with r where w.get() == dynamic_cast<T *>(r.get()) and w.use_count() == r.use_count(), otherwise an empty shared_ptr<T> is returned.

std::reinterpret_pointer_cast:

For C++17, N3920 (adopted into Library Fundamentals TS in February 2014) also proposed a std::reinterpret_pointer_cast similar 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_ptr casts and extended shared_ptr to support arrays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文