为啥这个自定义指针类会崩溃?
Posted
技术标签:
【中文标题】为啥这个自定义指针类会崩溃?【英文标题】:Why does this custom pointer class crash?为什么这个自定义指针类会崩溃? 【发布时间】:2018-04-15 19:39:29 【问题描述】:我正在实现一个特殊用途的句柄类。
ihandle
是一个所有句柄都必须实现的接口,在我的真实代码中,它将具有->
*
的运算符重载。但是对于这个例子,我想保持简单,它只有get
函数。
template <typename T>
class ihandle
public:
virtual T* get();
;
一种可能的实现是ptr
,它只是一个原始指针。
template <typename T>
class ptr : public ihandle<T>
T* t;
public:
ptr(T* t = nullptr) : t(t)
T* get()return t;
;
然后是handle
,用于进行空安全检查。
template <typename T>
class handle
public:
ihandle<T>* h;
T* get()return h->get();
handle(ihandle<T>* h = nullptr) : h(h)
template <typename D>
handle(handle<D>& hd)
: h((ihandle<T>*)hd.h)
static_assert(is_base_of<T, D>::value, "error");
;
有这个构造函数可以将继承类的句柄转换为基类的句柄。
template <typename D>
handle(handle<D>& hd)
: h((ihandle<T>*)hd.h)
static_assert(is_base_of<T, D>::value, "error");
例如,如果B
继承自A
,我希望能够使用handle<B>
的实例调用此函数。
void foo(handle<A> ha)
// do something
但这会导致以下示例测试出现段错误。
struct A
virtual void talk() printf("A\n");
;
struct B : public A
void talk() printf("B\n");
;
int main()
handle<B> hb(new ptr<B>(new B));
//hb.get()->talk(); // if uncomment, no segfault
handle<A> ha = hb;
ha.get()->talk(); // segfault here
return 0;
我怀疑问题可能出在 handle(handle<D>& hd)
构造函数中,但我不明白发生了什么。
您可以通过单击此链接对其进行测试: https://onlinegdb.com/BkAYuQZ3z
【问题讨论】:
你没有适当的复制构造函数来正常工作handle<A> ha = hb;
... mabbe 规则五和零是你应该查找的东西
【参考方案1】:
即使条件is_base_of<T, D>::value
为真,它也不会使(ihandle<T>*) hd.h
强制转换有效,因为ptr<B>
和ihandle<A>
类型不相关。我想这是一个绝对应该避免使用 c 风格转换的例子。为了安全地执行转换,您可以使用dynamic_cast
进行检查:
: h(dynamic_cast<ihandle<T>*>(hd.h))
if(hd.h && !h)
throw ::std::runtime_error"pointers are not related";
【讨论】:
我想允许从handle<B>
向上转换到handle<A>
,dynamic_cast
也允许从handle<A>
向下转换到handle<B>
。 runtime_error
与您提供的代码一起抛出。谢谢!
如果您想让handle<B>
到handle<A>
的转换工作,那么您只需要存储指向根目标类型的指针(ihandle<A> * h;
在handle<B>
和handle<A>
中)或进行类似 COM 的 QueryInterface
方法。【参考方案2】:
问:您使用的是什么编译器/链接器?当我使用 VS-2017 编译你的东西时,我得到一个链接器错误。它说当我在你的主测试中包含 hb 的声明时,它需要一个 B->get(),
handle<B> hb(new ptr<B>(new B));
..但是当我为虚拟方法 ihandle.get() 提供一些默认实现时,像这样..
template <typename T>
class ihandle
public:
virtual T* get() return NULL;
;
return NULL.. 我的链接器错误消失了.. 并且没有崩溃。您测试报告 B 或 B B。
希望我能提供帮助。感谢您的代码!我正在学习 C++ atm,上面的例子是一个很好的学习..
【讨论】:
有意思,我用的是gcc以上是关于为啥这个自定义指针类会崩溃?的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个自定义 UIView 代码不显示 UILabel 的?