So I have starting to learn Qt 4.5 and found the Signal/Slot mechanism to be of help. However, now I find myself to be considering two types of architecture.
This is the one I would use
class IDataBlock
{
public:
virtual void updateBlock(std::string& someData) = 0;
}
class Updater
{
private:
void updateData(IDataBlock &someblock)
{
....
someblock.updateBlock(data);
....
}
}
Note: code inlined for brevity.
Now with signals I could just
void Updater::updateData()
{
...
emit updatedData(data);
}
This is cleaner, reduces the need of an interface, but should I do it just because I could? The first block of code requires more typing and more classes, but it shows a relationship. With the second block of code, everything is more "formless". Which one is more desirable, and if it is a case-by-case basis, what are the guidelines?
A slot is called when a signal connected to it is emitted. Slots are normal C++ functions and can be called normally; their only special feature is that signals can be connected to them. Since slots are normal member functions, they follow the normal C++ rules when called directly.
A public slots section contains slots that anyone can connect signals to. This is very useful for component programming: you create objects that know nothing about each other, connect their signals and slots so that information is passed correctly, and, like a model railway, turn it on and leave it running.
If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted. Signals are automatically generated by the moc and must not be implemented in the . cpp file. They can never have return types (i.e.
Emmitting a signal costs few switches and some additional function calls (depending on what and how is connected), but overhead should be minimal.
Provider of a signal has no control over who its clients are and even if they all actually got the signal by the time emit returns.
This is very convenient and allows complete decoupling, but can also lead to problems when order of execution matters or when you want to return something.
Never pass in pointers to temporary data (unless you know exactly what you are doing and even then...). If you must, pass address of your member variable -- Qt provides a way to delay destruction of object untill after all events for it are processed.
Signals also might requre event loop to be running (unless connection is direct I think).
Overall they make a lot of sense in event driven applications (actually it quickly becomes very annoying without them).
If you already using Qt in a project, definitely use them. If dependency on Qt is unacceptable, boost has a similar mechanism.
There is another difference. #1 is hard coupled to the IDataBlock interface, and the Updater class needs to know about "someblock". #2 can be late-coupled via a connect call (or several, including disconnects), which leads to a more dynamic approach. #2 acts like a message (think Smalltalk/ObjC) and not a call (think C/C++). Messages can also be subject to multiple dispatch, which requires hand implementing that feature in #1.
My preference would be to utilize signals/slots due to their flexibility, unless code performance or the need for immediate return data does not allow for it (or the dependence on Qt is not desirable).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With