Using Emit VS Calling a Signal as If It's a Regular Function in Qt

Using emit vs calling a signal as if it's a regular function in Qt

emit is just syntactic sugar. If you look at the pre-processed output of function that emits a signal, you'll see emit is just gone.

The "magic" happens in the generated code for the signal emitting function, which you can look at by inspecting the C++ code generated by moc.

For example a foo signal with no parameters generates this member function:

void W::foo()
{
QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

And the code emit foo(); is pre-processed to simply foo();

emit is defined in Qt/qobjectdefs.h (in the open-source flavor of the source anyway), like this:

#ifndef QT_NO_EMIT
# define emit
#endif

(The define guard is to allow you to use Qt with other frameworks that have colliding names via the no_keywords QMake config option.)

Call function directly vs emiting Signal (Qt - Signals and Slots)

Signals and slots are used to decouple classes so that they don't need to explicitly know who uses their functionality and how. In many cases, decoupling is a desirable trait of the design of your software. Of course it's not an end in itself, it's useful when it helps you to reason about the code's correctness and makes it easier to maintain. Decoupling help in understanding/reasoning about the code as it leads to smaller units of code that you can analyze in isolation. Another way to look at it is separation of concerns: let one unit of code do one thing, e.g. focus one class on one aspect of functionality.

When you have a pair of classes and wish to decide whether to couple them or not, think of whether they could be used with other classes. A could be coupled to B, but could the interface that couples the pair be used by C instead of B? If so, then some decoupling pattern must be used, and signal-slot pattern is one of them.

For example, let's compare how these two interfaces affect coupling with user code. The objective is simple: add debug output to an object's destructor:

class QObject {
...
Q_SIGNAL void destroyed(QObject * obj = Q_NULLPTR);
};

class QObjectB {
...
virtual void on_destroyed();
};

int main() {
QObject a;
struct ObjectB : QObjectB {
void on_destroyed() override { qDebug() << "~QObjectB"; }
} b;
QObject::connect(&a, &QObject::on_destroyed, []{ qDebug() << "~QObject"; });
}

The signal-slot interface allows you to easily add functionality to existing objects without a need to subclass them. It is a particularly flexible implementation of the Observer pattern. This decouples your code from the code of the objects.

The second implementation, using the template method lookalike pattern, forces a closer coupling: to act on ObjectB's destruction, you must have an instance of a derived class where you implement the desired functionality.

Using Qt signals and slots vs calling a method directly

The main difference, in your example, of using a signal instead of a direct call, is to allow more than one listener.

If you directly call your widget setValue(), then only that one widget will receive the C++ signal.

If you use a Qt signal, now any other object can connect to receive the event whenever it occurs.

If you do not foresee any other object to ever want to receive the value by signal, I would not bother with such. A direct call is definitively a lot faster (between 3 and 6 CPU instructions instead of dealing with strings to find receivers!), but as Paranaix mentioned, in a GUI it may not be much of an issue (although in this case it could become a problem on older computers if you send all those signals while moving the sliderbar.)

Qt 4.5 - Is emitting signal a function call, or a thread, and does it blocks?

It depends. From the documentation:

When a signal is emitted, the slots connected to it are usually executed immediately, just like a normal function call. When this happens, the signals and slots mechanism is totally independent of any GUI event loop. Execution of the code following the emit statement will occur once all slots have returned. The situation is slightly different when using queued connections; in such a case, the code following the emit keyword will continue immediately, and the slots will be executed later.

So in normal cases, it will be synchronous and blocking, and with queued connections it will be asynchronous and non-blocking.

Qt - emitting slots instead of signals

If you look at the definition of emit, you can see that it is empty. emit is just used to indicate that a signal is emitted at that line. Therefore, emitting a slot does not make sense.

Slots are regular functions, you can call them explicitly.

QT error when emit a signal from a function

The Q_OBJECT macro is missing

Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the Meta Object Compiler on the source file. We strongly recommend the use of this macro in all subclasses of QObject regardless of whether or not they actually use signals, slots and properties, since failure to do so may lead certain functions to exhibit strange behavior.

Whats the difference between a normal function and a slot in Qt?

The difference is that slots with get MOC treatment and generate meta data, which is required for certain Qt functionality that involves runtime lookup by member names passed as strings.

For connections alone, plain member functions are perfectly OK since Qt 5 using the new connection syntax.

For Qt 4 you have no option but to use slots.



Related Topics



Leave a reply



Submit