发射Qt信号时是否有可能抛出异常?

时间:2013-06-19 21:04:28

标签: c++ qt

在查看一些代码时,我发现了一段代码:

struct MyFooStructure
{
  //Nothing unusual, just basic types
}

class Foo : public QObject
{
   Q_Object

public:
   void fooMethod(const MyStructure &s);

signals:
   void fooSignal(const MyStructure &);
}

void Foo::fooMethod(const MyStructure &s)
{
   try
   {
      emit fooSignal(s)
   }
   catch(const std::exception &e)
   {
      qDebug() << "An exception!";
   }
}

有没有可能进入这里的渔获物?据我所知,没有可能的异常被抛出:emit is just a macro to create a table to call the appropriate functions connected to that signal on the *.moc file。是真的需要尝试抓住吗?

1 个答案:

答案 0 :(得分:6)

是的,在您的示例中需要捕获,至少如果连接到fooSignal的任何插槽抛出std::exception

语句emit fooSignal();同步调用所有连接的插槽。基本上QObject内部有一个连接表,它在其中存储对象的所有连接,每个插槽都是一个函数指针。基本上emit所做的(或者更确切地说,moc生成的fooSignal实现的内容)是它只是迭代连接表并为每个连接的槽调用所有函数指针。

因此,在连接语句中从调用插槽。这也意味着如果任何插槽抛出异常,异常将传播到emit语句之外。

请注意,fooSignal的内部moc生成代码仅是最近的异常安全,请参阅Olivier在this bug report上的回答。这意味着旧版本的Qt无法处理插槽中抛出的异常,如果插槽抛出异常,则moc生成的代码将以未定义的方式失败。

编辑:我还想补充说,拥有抛出异常的插槽是不好的做法,试着避免这种情况。调用emit的代码不知道连接的是哪些插槽,因此它不知道需要捕获哪些异常。此外,只要您有排队连接而不是直接连接,就会异步调用插槽而不是同步调用插槽,并且您将无法捕获插槽的异常。