通过 QT 的信号/槽系统作为参数传递通用异常
Posted
技术标签:
【中文标题】通过 QT 的信号/槽系统作为参数传递通用异常【英文标题】:Pass generic exception through QT's signal/slot system as argument 【发布时间】:2015-09-05 10:05:57 【问题描述】:当我捕获一个异常时,我想发出一个信号并将该异常传递给一个槽,以便它可以在不同的线程中处理。信号和槽使用 Qt:QueuedConnection 类型连接。
我第一次尝试这个:
/*in .h*/
signals:
void exceptionOccured(const std::exception &e);
public slots:
void exceptionReceive(const std::exception &e);
/*in .cpp*/
connect(this,SIGNAL(exceptionOccured(const std::exception&)),this,SLOT(exceptionReceive(const std::exception&)),Qt::QueuedConnection);
try
throw std::runtime_error("test");
catch (std::exception &e)
emit exceptionOccured(e);
这有点工作,但是当 QT 将引用对象的副本放置在队列中时,exceptionReceived 插槽接收到 std::exception 类型的对象并且所有附加信息都丢失了。
然后我尝试传递一个指向原始异常对象的指针,但这给了我一个问题,即当插槽被调用时,实际对象已经消失了。
如何告诉 QT 制作异常的正确副本(实际应用程序从 std::exception 继承了多个级别)或将捕获的异常转换为某种安全指针类型(即从堆栈到堆左右)。
附: 对象将消息发送给自己,因为 try/catch 语句是使用 QtConcurrent::run() 从 lambda 函数运行的;
【问题讨论】:
您可以将std::exception
包裹在一个类中,该类将对必要数据进行深度复制。
如果您使用的是 C++11,那么 std::exception_ptr
会有所帮助。
@AlanStokes 是的,我使用 C++11 并且使用 std::current_exception() 确实允许我在另一个线程中使用异常。如果你把它作为一个答案,那么我可以标记它。
【参考方案1】:
std::exception_ptr
被添加到标准 C++11 中,以解决这个问题。 std::current_exception()
可让您获得当前异常的句柄,然后您可以将其传递并在您想要的任何线程中重新抛出它。
详情请见http://en.cppreference.com/w/cpp/error/exception_ptr。
【讨论】:
你确定它会一直有效吗? ref。 “std::exception_ptr
[...] 保存对该异常对象的副本或引用(如果进行了副本,则由实现定义)”。异常通常不需要是可复制的,但这通常要求它们是可复制的,并且它们的复制构造函数动作适当。此外,如果我错了,请纠正我,但有些(如果不是全部)标准异常类型是不可复制的(std::range_error
)。是的,base std::exception
是,但这没有帮助。
@Kuda 我相信所有异常类型都必须是可复制的——throw x
复制 x
(尽管可以省略复制)。我也相信range_error
是可复制的。我记得这里的副本是实现定义的原因是为了应对 MS 和 GCC 模型。【参考方案2】:
如果你坚持使用基本异常类型,那么这是一个 C++ 问题,而不是 Qt 问题。您需要实现某种类型的虚拟复制构造函数模式。一旦你这样做了,Qt 会自动做正确的事情。
这样一种模式:
class clonable_exception : public std::exception
protected:
virtual void clone_to(clonable_exception& dst) const = 0;
public:
clonable_exception() = default;
clonable_exception(const clonable_exception& src)
src.clone_to(*this);
clonable_exception & operator=(const clonable_exception& src)
src.clone_to(*this);
;
所有信号和槽都应该使用clonable_exception
类型而不是std::exception
。
【讨论】:
以上是关于通过 QT 的信号/槽系统作为参数传递通用异常的主要内容,如果未能解决你的问题,请参考以下文章