C++ 如何在Qt中捕获异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10075792/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to catch exceptions in Qt?
提问by smallB
try
{ // `count()` throws exception
connect(thread, SIGNAL(started()), engine, SLOT(count()));
}
catch(const X& e)
{}
As of Qt-5, I get following error:
从 Qt-5 开始,我收到以下错误:
Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must not let any exception whatsoever propagate through Qt code. If that is not possible, in Qt 5 you must at least re-implement
QCoreApplication::notify()
and catch all exceptions there.
Qt 已捕获从事件处理程序抛出的异常。Qt 不支持从事件处理程序中抛出异常。你不能让任何异常通过 Qt 代码传播。如果这是不可能的,在 Qt 5 中,您至少必须重新实现
QCoreApplication::notify()
并捕获那里的所有异常。
If I can't catch the exceptions in conventional way as shown above, then where are we supposed to catch those?
如果我不能如上所示以常规方式捕获异常,那么我们应该在哪里捕获这些异常?
采纳答案by cgmb
where am I supposed to catch it?
我应该在哪里抓住它?
This is exactly why Qt does not support throwing exceptions across signal/slot connections. If you try it, you'll see this message:
这正是 Qt 不支持跨信号/插槽连接抛出异常的原因。如果您尝试一下,您将看到以下消息:
Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must reimplement QApplication::notify() and catch all exceptions there.
Qt 已捕获从事件处理程序抛出的异常。Qt 不支持从事件处理程序中抛出异常。您必须重新实现 QApplication::notify() 并在那里捕获所有异常。
As it mentions, it is possible to subclass QApplication and catch your exception there, but that will be a very annoying way of handling things.
正如它所提到的,可以将 QApplication 子类化并在那里捕获您的异常,但这将是一种非常烦人的处理方式。
If possible, I would recommend rewriting count such that it does not throw.
如果可能,我建议重写 count 使其不会抛出。
What if you can't rewrite count()?
如果你不能重写 count() 怎么办?
For example, what if count() is part of a function in a 3rd-party library that you're using?
例如,如果 count() 是您正在使用的第 3 方库中函数的一部分怎么办?
No slot in any official Qt library throws, so if you're using a third-party library with a slot that throws, it's probably a sign that it's not a good library. If you want to use it anyway, I recommend that rather than catching it in QApplication::notify
, that you instead create an adapter.
任何官方 Qt 库中都没有抛出异常的插槽,因此如果您使用带有抛出异常的插槽的第三方库,则可能表明它不是一个好的库。如果您无论如何都想使用它,我建议您不要使用它,QApplication::notify
而是创建一个适配器。
What does that mean? First create an object that takes in your sketchy third-party object in the constructor. In it, write a slot that wraps a call to the throwing slot with a try/catch block. Now instead of connecting to the sketchy third-party object's slot, connect to your newly create object's slot.
这意味着什么?首先创建一个对象,该对象在构造函数中接收您粗略的第三方对象。在其中,编写一个槽,用 try/catch 块包装对抛出槽的调用。现在不是连接到粗略的第三方对象的插槽,而是连接到新创建的对象的插槽。
Doing the exception catching this way keeps related code together, and prevents QApplication::notify
from filling up with a bunch of unrelated try/catch blocks if you encounter more than one of these problematic functions.
以这种方式进行异常捕获将相关代码保持在一起,并防止QApplication::notify
在遇到多个这些有问题的函数时填充一堆不相关的 try/catch 块。
For example:
例如:
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;
}
What if you want to handle something that could be thrown from anywhere?
如果你想处理可以从任何地方抛出的东西怎么办?
The obvious example of this sort of global concern is an unexpected exception. Mistakes can happen anywhere. It would be desirable to log as many details about the event as possible so the cause could be identified and corrected. In this case, you wouldwant to reimplement QApplication::notify
in your own subclass as shown in jichi's answer. Using a global handler for global concerns is quite reasonable.
这种全球关注的明显例子是一个意想不到的例外。错误可能发生在任何地方。最好记录尽可能多的事件详细信息,以便确定并纠正原因。在这种情况下,您可能希望QApplication::notify
在自己的子类中重新实现,如jichi 的回答所示。使用全局处理程序处理全局问题是非常合理的。
回答by jichi
If someone needs an example code to override QApplication::notify, I got one from here (in Japanese): http://www.02.246.ne.jp/~torutk/cxx/qt/QtMemo.html
如果有人需要一个示例代码来覆盖 QApplication::notify,我从这里得到了一个(日语):http: //www.02.246.ne.jp/~torutk/cxx/qt/QtMemo.html
#include "MyApplication.h"
#include <exception>
MyApplication::MyApplication(int& argc, char** argv) :
QApplication(argc, argv) {}
bool MyApplication::notify(QObject* receiver, QEvent* event) {
bool done = true;
try {
done = QApplication::notify(receiver, event);
} catch (const std::exception& ex) {
// ログや何らかの回復処理
} catch (...) {
// ログや何らかの回復処理
}
return done;
}
回答by Adrian
You can try this for an example, to see that your solution is good:
你可以试试这个例子,看看你的解决方案是好的:
int f()
{
throw 1;
return 5;
}
void g(int x)
{
cout << x << endl;
}
int main()
{
try {
g(f());
}catch(int)
{
cout << "Caught exception" << endl;
}
}