Reputation: 1776
While reviewing some code, I found a piece of code like that:
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!";
}
}
Is there any possibility to enter on the catch here? As far as I know, there are no possible exception being thrown: emit is just a macro to create a table to call the appropriate functions connected to that signal on the *.moc file. Is that try catch really needed?
Upvotes: 3
Views: 1832
Reputation: 5466
Yes, the catch is needed in your example, at least if any slots connected to fooSignal
throw an std::exception
.
The statement emit fooSignal();
calls all connected slots synchronously. Basically QObject
internally has a connection table in which it stores all connections for an object, which each slot being a function pointer. Basically what emit
does (or rather, what the moc-generated implementation of fooSignal
does) is that it simply iterates over the connection table and calls all function pointers for each connected slot.
So the slots are called from within the connect statement. That also means if any slots throw an exception, the exception will propagate outside of the emit
statement.
Note that the internal moc-generated code for fooSignal
is only exception-safe as of recent, see Olivier's answer on this bug report. That means older versions of Qt can't deal with exceptions being thrown in slots, and the moc-generated code will fail in undefined ways if slots throw an exception.
EDIT: I also want to add that having slots that throw exceptions is bad practice, try avoiding that. The code that calls emit
doesn't know what slots are connected, so it doesn't know what exceptions it needs to catch. Furthermore, as soon as you have queued connections instead of direct connections, the slots will be called asynchronously instead of synchronously, and you won't be able to catch the slots' exceptions.
Upvotes: 6