如何在Qt中捕获异常
How to catch exceptions in Qt?
try
{ // `count()` throws exception
connect(thread, SIGNAL(started()), engine, SLOT(count()));
}
catch(const X& e)
{}
从Qt-5开始,我收到以下错误:
Qt 捕获了从事件处理程序引发的异常。扔 Qt 不支持来自事件处理程序的异常。 您不能让任何异常通过Qt代码传播。 如果这是不可能的,在Qt 5中,你至少必须重新实现。
QCoreApplication::notify()
并捕获那里的所有异常。
如果我无法以传统方式捕获异常,如上所示,那么我们应该在哪里捕获这些异常?
我应该在哪里抓住它?
这正是Qt不支持跨信号/插槽连接抛出异常的原因。如果您尝试,您将看到以下消息:
Qt 捕获了从事件处理程序引发的异常。扔 Qt 不支持来自事件处理程序的异常。你必须 重新实现 QApplication::notify() 并捕获那里的所有异常。
正如它所提到的,可以对QApplication进行子类化并在那里捕获异常,但这将是一种非常烦人的处理方式。
如果可能的话,我建议重写计数,使其不会抛出。
如果无法重写 count() 怎么办?
例如,如果 count() 是您正在使用的第三方库中函数的一部分怎么办?
任何官方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 的答案所示。使用全局处理程序来处理全局问题是非常合理的。
如果有人需要一个示例代码来覆盖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;
}
您可以尝试此操作,以查看您的解决方案是否良好:
int f()
{
throw 1;
return 5;
}
void g(int x)
{
cout << x << endl;
}
int main()
{
try {
g(f());
}catch(int)
{
cout << "Caught exception" << endl;
}
}
- 当类定义不可见时捕获异常
- 来自 Android 应用程序内部的 boost 类型的 boost::wrapexcept<boost::system::system_error> 的未捕获异常
- 如何通过 pybind11 从 python 中的C++中捕获异常?
- 信号后未捕获异常
- 捕获异常后如何退出程序执行
- C++ 捕获异常后进行清理的标准方法是什么?
- 使用模板类引发和捕获异常
- E/libc++abi:终止于类型为google::protobuf::FatalException的未捕获异常
- 如果在生成 std::thread 后引发,则未捕获异常
- C++ 未捕获异常,程序将终止并中止
- C++程序在第一次尝试时会给出垃圾,但如果它捕获异常并重试,则会给出适当的值
- 仅捕获异常就可以检测所有二进制文件在C 中读取错误是否足够
- 如何捕获 I/O 异常(确切地说是 I/O,而不是 std::exception)
- 为什么捕获异常播放允许尾括号
- throw() 函数应该总是在异常时展开堆栈并允许捕获异常还是必须调用 std::terminate ?
- 寻求与类型为 std::invalid_argument 的未捕获异常相关的运行时错误的建议: stoi:无转换
- 如何从调用函数中捕获异常
- 当用户在字符数组中输入整数值时捕获异常
- C++按值捕获异常时的示例是不好的
- 如何在Qt中捕获异常