c – 如何捕获Qt中的异常?

try
{  // `count()` throws exception
  connect(thread, SIGNAL(started()), engine, SLOT(count()));  
}
catch(const X& e)
{}

从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.

如果我不能像上面所示那样以传统的方式捕捉异常,那么我们应该把它们赶上哪些?

解决方法:

where am I supposed to catch it?

这正是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.

正如它提到的那样,可以将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’s answer所示.对全局关注使用全局处理程序是非常合理的.

上一篇:c – C2440:’=’:无法从’const char [9]’转换为’char *’


下一篇:c – 在Ubuntu的QT5中将透明QWidget置于QMediaView之上