如何使用unique_ptr执行dynamic_cast?

Sha*_*ath 21 c++ boost dynamic-cast smart-pointers unique-ptr

我有一个类层次结构如下:

class BaseSession : public boost::enable_shared_from_this<BaseSession>
class DerivedSessionA : public BaseSession
class DerivedSessionB : public BaseSession
Run Code Online (Sandbox Code Playgroud)

在派生类函数中,我经常调用这样的函数:

Func(boost::dynamic_pointer_cast<DerivedSessionA>(shared_from_this()));
Run Code Online (Sandbox Code Playgroud)

由于我正在与shared_ptr管理会议,这工作正常.最近,我发现我shared_ptr对这种情况的使用不是最佳的.这是因为这些会话是单个对象,每个客户端维护一个套接字.如果重新连接套接字,则会话副本将成为僵尸.

作为解决方法,我开始通过shared_ptr引用传递而不是复制.这解决了僵尸问题.

理想情况下,我觉得我应该unique_ptr用来存储会话,然后将引用传递给其他函数.这打开了一大堆蠕虫.

如何将基类unique_ptr对象转换为派生类unique_ptr对象?unique_ptr以下行的版本是什么?

Func(boost::dynamic_pointer_cast<DerivedSessionA>(shared_from_this()));
Run Code Online (Sandbox Code Playgroud)

我只想要一个会话对象的副本,其他一切都应该是参考.

seh*_*ehe 24

更新

问题已得到澄清:

对不起,我不清楚.我希望所有权保留在原始所有者身上,被调用的函数应该只引用它,而不是所有权.没有为同一个对象寻找两个智能指针.

在这种情况下,解决方案很简单:

dynamic_cast<B&>(*my_unique_ptr)
Run Code Online (Sandbox Code Playgroud)

做完了.如果演员阵容没有成功,它会抛出.


铸件 shared_ptr

因为shared_ptrstd::dynamic_pointer_cast<>(http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)

铸件 unique_ptr

最简单的方法似乎是:

#include <memory>

struct A { virtual ~A() = default; };
struct B : A { };

int main()
{
    std::unique_ptr<A> pa(new B);

    std::unique_ptr<B> pb(dynamic_cast<B*>(pa.release())); // DO NOT DO THIS
}
Run Code Online (Sandbox Code Playgroud)

正如评论者正确指出的那样,如果转换失败,这可能会泄漏对象.这不是很有帮助.

dynamic_unique_ptr_cast<>不存在的原因可能是该unique_ptr类型不会删除删除器.可能很难/不可能为目标指针类型选择适当的删除.

但是,对于简单的情况,您可以使用以下内容:

template <typename To, typename From, typename Deleter> 
    std::unique_ptr<To, Deleter> dynamic_unique_cast(std::unique_ptr<From, Deleter>&& p) {
        if (To* cast = dynamic_cast<To*>(p.get()))
        {
            std::unique_ptr<To, Deleter> result(cast, std::move(p.get_deleter()));
            p.release();
            return result;
        }
        return std::unique_ptr<To, Deleter>(nullptr); // or throw std::bad_cast() if you prefer
    }


auto pb = dynamic_unique_cast<B>(std::move(pa));
Run Code Online (Sandbox Code Playgroud)

  • 是的,在过去的两天里,这篇文章发出了很多噪音.我试图在最后一次尽可能保留价值,但这种讨论已经持续太久了,似乎不会很快见效.要么让它聊天,要么你们中的一个可以问一个关于这个问题的新问题,让一个冷静的第三方找出正确的答案. (2认同)

Jar*_*d42 10

除非您想转移您的所有权,否则您std::unique_ptr<T>的函数应该使用指针或引用T.

所以签名Func应该是这样的Func(DerivedSessionA*)

然后你的电话可能看起来像:

std::unique_ptr<BaseSession> ptr; // Initialize it with correct value

Func(dynamic_cast<DerivedSessionA*>(ptr.get()));
Run Code Online (Sandbox Code Playgroud)

或者您似乎直接从以下方法中调用它BaseSession:

Func(dynamic_cast<DerivedSessionA*>(this));
Run Code Online (Sandbox Code Playgroud)