我应该在哪里抓到它?
这正是 Qt 不支持跨信号/插槽连接抛出异常的原因。如果您尝试一下,您将看到以下消息:
Qt 已捕获从事件处理程序抛出的异常。Qt 不支持从事件处理程序中抛出异常。您必须重新实现 QApplication::notify() 并在那里捕获所有异常。
正如它所提到的,可以将 QApplication 子类化并在那里捕获您的异常,但这将是一种非常烦人的处理方式。
如果可能的话,我建议重写 count 使其不会抛出。
如果你不能重写 count() 怎么办?
例如,如果 count() 是您正在使用的第 3 方库中某个函数的一部分怎么办?
任何官方 Qt 库中都没有任何插槽抛出,所以如果您使用的第三方库带有一个抛出的插槽,这可能表明它不是一个好的库。如果您仍然想使用它,我建议QApplication::notify
您创建一个适配器,而不是将其捕获。
这意味着什么?首先在构造函数中创建一个对象,该对象接受您粗略的第三方对象。在其中,编写一个插槽,该插槽使用 try/catch 块包装对投掷插槽的调用。现在,不要连接到粗略的第三方对象的插槽,而是连接到新创建的对象的插槽。
以这种方式进行异常捕获可以将相关代码保持在一起,并防止QApplication::notify
在遇到多个这些有问题的函数时填充一堆不相关的 try/catch 块。
例如:
class BadCounter {
Q_OBJECT
public slots:
void count() { throw CounterError("unable to count"); }
};
class CounterAdaptor {
Q_OBJECT
BadCounter* counter_;
public:
CounterAdaptor(BadCounter* counter) {
counter_ = counter;
}
public slots:
void count() {
try {
counter_->count();
} catch (const CounterError& e) {
std::cerr << e.what() << std::endl;
}
}
};
int main() {
BadCounter engine;
CounterAdaptor adaptor(&engine);
QThread* thread = new QThread();
connect(thread,SIGNAL(started()),&adaptor,SLOT(count()));
thread.start();
... // etc...
delete thread;
}
如果您想处理可能从任何地方扔出的东西怎么办?
这种全球关注的明显例子是一个意外的例外。错误可能发生在任何地方。最好记录尽可能多的有关事件的详细信息,以便识别和纠正原因。在这种情况下,您可能希望QApplication::notify
在自己的子类中重新实现,如jichi 的答案所示。使用全局处理程序来处理全局问题是非常合理的。