c – 为什么这个自定义指针类会崩溃?
发布时间:2020-12-16 09:20:32 所属栏目:百科 来源:网络整理
导读:我正在实现一个特殊目的句柄类. ihandle是一个所有句柄必须实现的接口,在我的实际代码中,它将具有运算符重载 – *.但是对于这个例子,我想保持简单,它只有get函数. template typename Tclass ihandle {public: virtual T* get();}; 一种可能的实现是ptr,它只
我正在实现一个特殊目的句柄类.
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;} }; 然后有一个句柄,用于进行空安全检查. 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,"error"); } 例如,如果B继承自A,我希望能够使用句柄< B>的实例调用此函数. void foo(handle<A> ha) { // do something } 但这为以下样本测试提供了一个段落错误. struct A { virtual void talk() {printf("An");} }; struct B : public A { void talk() {printf("Bn");} }; 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; } 我怀疑问题可能在句柄(句柄< D>& hd)构造函数中,但我不明白发生了什么. 您可以点击此链接进行测试: 解决方法
即使条件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"}; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |