如何在 shared_ptr 的子类之间进行转换?
How do I cast between subclasses of shared_ptr?
我正在对 std::shared_ptr
进行子类化,并试图在子类上编写 cast()
方法以便隐藏 static_pointer_cast
,但我的代码无法编译。我错过了什么?
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;
...
我正在对 std::shared_ptr
进行子类化,并试图在子类上编写 cast()
方法以便隐藏 static_pointer_cast
,但我的代码无法编译。我错过了什么?
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;
...