如何在 shared_ptr 的子类之间进行转换?

How do I cast between subclasses of shared_ptr?

我正在对 std::shared_ptr 进行子类化,并试图在子类上编写 cast() 方法以便隐藏 static_pointer_cast,但我的代码无法编译。我错过了什么?

演示:http://ideone.com/nbPHbs

template<class T>
class Handle : public std::shared_ptr<T> {
public:
    template<class ResultType>
    inline Handle<ResultType>
    cast() {
        // Cast Handle to shared_ptr
        auto T_sp = static_cast< std::shared_ptr<T> >(*this);
        // Cast the data
        auto ResultType_sp = std::static_pointer_cast<ResultType>(T_sp);
        // Cast back to Handle
        return static_cast< Handle<ResultType> >(ResultType_sp);
    }
};


// Usage
struct Base {};
struct Child : public Base {};
auto child_ptr = Handle<Child>(new Child());
auto base_ptr  = child_ptr.cast<Base>(); // Error with this

这是我收到的错误消息:

error: no matching function for call to 'Handle<Child>::Handle(Child*)'
auto child_ptr = Handle<Child>(new Child());
                                         ^

**编辑 我在这里使用继承是因为 write-once/throw-away 代码最初是 template<T> using std::shared_ptr<T> Handle<T>; 因此,继承是需要最少代码更改的自然进展。因为看起来这段代码确实会保留一段时间,所以在发布这个 SO 问题之前我确实切换到了组合,我只是想知道为什么它没有编译;几年没搞过c++了,有点生疏了

您的 class 没有任何构造函数,因此,当您尝试编译时,如果您尝试使用带参数的构造函数,它将悲惨地失败。

如果你想继承自shared_ptr(我不鼓励这样做,因为基类析构函数不是虚拟的,你的程序很可能会严重泄漏内存)你应该添加class 正文中的这一行:

using std::shared_ptr<T>::shared_ptr;

我看不出在这里继承 shared_ptr 有什么好处,恕我直言,这不值得麻烦。如果你觉得 std::static_pointer_cast 又大又丑,你可以通过内联函数

来解决
template <typename TOUT, typename TIN>
inline std::shared_ptr<TOUT> cast(TIN in)
{
    return std::static_pointer_cast<TOUT>(in);
}

// Usage
struct Base {};
struct Child : public Base {};

int main() {
    std::shared_ptr<Child> child_ptr = std::make_shared<Child>();
    std::shared_ptr<Base> base_ptr  = cast<Base>(child_ptr); // Error with this
    return 0;
}

这个答案跳过了关于从 std::shared_ptr 继承是否是一个好主意的讨论。不过,我建议在继续之前先阅读此类讨论。

现在解决您眼前的问题:

如果你真的想继续这条路线,那么你缺少的就是构造函数。 编译器只是为你创建一个默认的构造函数。 如错误消息所示,您需要 Handle<Child>::Handle(Child*).

获得所需构造函数的最简单方法是重用基础 class:

template<class T>
class Handle : public std::shared_ptr<T> {
public:
    using std::shared_ptr<T>::shared_ptr;
...