在查看一些代码时,我发现了一段代码:
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。是真的需要尝试抓住吗?
答案 0 :(得分:6)
是的,在您的示例中需要捕获,至少如果连接到fooSignal
的任何插槽抛出std::exception
。
语句emit fooSignal();
同步调用所有连接的插槽。基本上QObject
内部有一个连接表,它在其中存储对象的所有连接,每个插槽都是一个函数指针。基本上emit
所做的(或者更确切地说,moc生成的fooSignal
实现的内容)是它只是迭代连接表并为每个连接的槽调用所有函数指针。
因此,在连接语句中从调用插槽。这也意味着如果任何插槽抛出异常,异常将传播到emit
语句之外。
请注意,fooSignal
的内部moc生成代码仅是最近的异常安全,请参阅Olivier在this bug report上的回答。这意味着旧版本的Qt无法处理插槽中抛出的异常,如果插槽抛出异常,则moc生成的代码将以未定义的方式失败。
编辑:我还想补充说,拥有抛出异常的插槽是不好的做法,试着避免这种情况。调用emit
的代码不知道连接的是哪些插槽,因此它不知道需要捕获哪些异常。此外,只要您有排队连接而不是直接连接,就会异步调用插槽而不是同步调用插槽,并且您将无法捕获插槽的异常。