Private slots question
-
I'm curios about a thing:
I noticed that a private slot can be called by any signal even if the object emmting it is not a class member toghether with the slot (as a normal method it can not be invoked by non member objects). This is mentioned in the docs but wouldnt it make more sense to be able to invoke a private slot only be member objects or friends and not by any object?
-
Not really, the private/public access is "checked" by the compiler at compile time, and the signal-slot connection is performed at run-time and slots are invoked by some QMetaObject mechanisms ("invokeMethod()":http://doc.qt.nokia.com/4.7/qmetaobject.html#invokeMethod).
So private slots are private if called as regular member functions but always public for connection.
Another example about some "weird" stuff can be the call of private virtual functions.
-
True it makes sense private protected and such are non existing at runtime i should have seen this earlier :D. Thanks.
-
Yes, and another thing is that private slots doesn't make sense for connections. Slots conceptually are public interface, since their main purpose is inter-object communication.
If you really need a function to be private that function shouldn't be a slot too, it should be just a private member function (if call that function internally you you just call the function, you don't need a connection for that)
-
Private/protected slots may make sense if you need them internally for a kind of more sophisticated widget. You want to connect them with a signal of a subwidget internally but won't expose them to the public API.
"PIMPL":http://www.qtcentre.org/wiki/index.php?title=Private_implementation does not help here, as the d-pointer objects are not QObject derived and thus cannot have slots.
Making the method simply private/protected (without slot keyword) would make it impossible to connect() too.
Of course, the private/protected slots can be connected to via signal/slots connection. But, you must look into the header files or ignore the protected in the documentation. In this case you should know what you do.
And as you mentioned, private/protected/public is checked at compile time[1]. So you always can fool the compiler by grabbing the original header file, move the private method to the public part and compile :-)
fn1. I'm not sure if some compiler (MS VC++?) includes the access level into the name mangling scheme.
-
[quote]
Private/protected slots may make sense if you need them internally for a kind of more sophisticated widge. You want to connect them with a signal of a subwidget internally but won’t expose them to the public API.
[/quote]Another pattern here is the Q_PRIVATE_SLOT mechanism. http://lists.trolltech.com/qt-interest/2008-04/msg00348.html
-
There is a possibility to apply a runtime check too:
You can do this in a private slot:
check if the sender of the signal is "this"
check if the sender is a friend class, in this case an object of type Object3 may call this slot.
@void Object1::mySlot()
{
if(sender() != this && sender()->metaObject()->className() != QString("Object3"))
{
qFatal("Object1::mySlot() is private and can not be called from %s", sender()->metaObject()->className());
}qDebug() << this << ": mySlot called by:" << sender();
}@
This is of course not fun to debug as you might only hit the fatal message by accident.
Edit: I'm sure I made a couple of mistakes here.
-
But if you do this,m internal slots will not work.
I use private slots for connections to shild objects. For example:I have a widget with a button. The button is cobnnected to a protected or private slot. The sender will not be this!!! For this, you normally do not need signals, only if you want to achieve some threadding stuff with queued connections.