In my one year of Qt programming, I have learnt a lot about signals and slots. But not enough...
http://doc.qt.io/qt-5/signalsandslots.html
S
Another use case where you possibly don't want all methods to be slots is when you are exposing objects to JavaScript through Qt's WebKit Bridge: all public slots are invocable from the JavaScript and that might open up security issues, depending on whether the JavaScript can be trusted or not.
So if you want a public method which is not invocable from JavaScript, you may not declare it as a slot.
In reference to encapsulation from code_fodder's answer, it should be noted that there's really no such thing as a private slot.
For example:
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass()
:QObject(NULL) {}
private slots:
void Hello() { qDebug("Hello World\n"); }
};
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyClass* cls = new MyClass;
QMetaObject::invokeMethod(cls, "Hello");
return a.exec();
}
As we can see here, calling the functionHello
is successful from outside the class.
For certain functions, you need a return value. This will not work as easily in slots. In slots you cant use the return value of a function or give a reference parameter to them. Yes you can do it, but you have a timing Problem. Whether you're using a slot or a normal member function dependents on your software architecture.
In addition, slots run in the event loop. It depends on your code if this is intentional or not.
In addition to ddriver's answer, which is the best / correct answer (+1 there), I would also argue that it is confusing to define all member functions as public slots. They way you define functions (private / public / slots etc...) has an effect on the perceived usage of the class.
What I mean by that is.... you could argue that all functions should just be public (or public slots) and then this covers all cases. However this could be confusing to a future user of your class. Consider that int value()
is a public slot (its not the best example) someone could try to use it as one, but the function itself has a return value which does not really make sense for a slot. It does make sense for a normal member function where (as a normal function call) the return value can be accessed.
One rule to go by is to always keep your functions and variables as local scoped and private as you can (by default) and only open them up for other use (public-ness, slots, global, etc...) when you really need them. This keeps your class interface much easier to understand and avoid confusion for later users.
I am sure there is a name for this rule-of-thumb so you can look it up on some coding technique site, but I can't recall it :(
edit
Another minor example is the auto complete... if all your functions are slots, then when you are doing your connect(this, myClass::mySignal, &someOtherClass, SomeOtherClass::<auto complete options> );
your list of auto complete options could be long and unclear what is what. If you just have a few specific members that are slots then its easier to know which to choose.
Back in the olden days, you had no choice but to use slots if you want to connect to signals. This is no longer the case in Qt 5, where connections can be made to regular member functions or even free functions or lambdas.
Declaring a slot registers that function into that particular object's meta data, making it readily available to all of Qt's functionality which relies on the meta object. Other than that, it is a regular member function as the documentation states. There is nothing special in the slot function itself, the difference is in the generation of meta data for it in the meta object.
This means that declaring slots comes at some cost, albeit a small one, both in compilation time and executable size. I'd say it is overkill to have all your public functions as slots. It would be more efficient to only use slots when you actually need slots, if it can't work with a regular function, make it a slot.
Also, note that in almost all of the cases, signals are declared with a return type void
. This has to do with the typical usage case of signals - they can often pass a parameter, but rarely return anything. Even though it is possible to return a value through a signal connected to a slot, this is used extremely rarely. So it doesn't make a lot of sense to declare a function that returns something as a slot you intend to connect to, as the very fact it returns a value means it will most likely not be used in the typical signal/slot context. That's why the getter is not a slot in that example. The setter as a slot is redundant in Qt 5, and is probably the product of this example code dating back to Qt 4.
Lastly, separating slots from regular public functions is a good way to illustrate intent, or the "API" of that class if you will. For example, I mostly use slots when extending QML, so I don't have to mark every function explicitly as invokable - unlike the scenario mentioned in the above paragraph, such slots often return stuff, but they aren't really used in connections. This way I get a clear overview of the design of the interface the class provides.