46

Can Qt signals be public, protected or private? Can I create internal signals, which are seen only inside the class?

Update: I have a class with some internal signals. How can I make those signals invisible for other classes (encapsulation & information hiding)?

mip
  • 8,355
  • 6
  • 53
  • 72
anton
  • 755
  • 2
  • 7
  • 9

8 Answers8

28

No. Signals cannot be public or private. Qt signals are protected class methods.

"signals" keyword is defined in qobjectdefs.h (line 69 as for Qt 4.6.1):

#   define signals protected

UPDATE: signals are only protected upto and including all minor versions of Qt 4. From Qt 5.0 onwards they are public. See https://stackoverflow.com/a/19130831.

Community
  • 1
  • 1
Andrei Vlasyuk
  • 289
  • 2
  • 4
  • 4
    I believe signals are now considered `public` see here http://stackoverflow.com/questions/19129133/qt-signals-and-slots-permissions/19130567#19130567 – johnbakers Oct 02 '13 at 05:40
  • It seems there can be private signals: http://doc.qt.io/qt-5/qstate.html#finished - just how are they created? – derM - not here for BOT dreams Jul 27 '17 at 14:35
  • The change was required to make use of C++11 syntax in `connect` functions, where the callback to the function is provided rather than named signal or slot. – mip Jul 24 '22 at 17:19
19

Signals was protected in Qt4, in Qt5 they are public. Int Qt5 you can make them private by adding QPrivateSignal as the last argument. More on this: http://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html

Nikita Krupenko
  • 1,117
  • 1
  • 13
  • 17
19

A common way, e.g. seen in kdelibs, is this:

Q_SIGNALS:
#ifndef Q_MOC_RUN
    private: // don't tell moc, doxygen or kdevelop, but those signals are in fact private
#endif

   void somePrivateSignal();

This makes the signal private, i.e. it can only be emitted by the class itself but not by its subclasses. To not make the "private:" overrule Q_SIGNALS (moc wouldn't see somePrivateSignal as signal then), it's inside Q_MOC_RUN, which is only defined when moc runs.

Edit: This approach doesn't work for the new-style connects introduced with Qt 5 (connect(a, &A::someSignal, b, &B::someSlot)), as they require the signal to be accessible.

Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • No, as "#define Q_SIGNALS protected", the private: won't have any effect – Frank Osterfeld Jan 09 '13 at 22:20
  • 1
    Drat. Why does everything in C++ require a hack? – weberc2 Jun 24 '13 at 17:34
  • *"This approach doesn't work for the new-style connects introduced with Qt 5"* -- depends... If one wants only to allow to connect to the signal internally, too (where the slot then possibly might emit another, then public signal), then this is *ideal* -- except for that the old syntax still would allow to connect to it... – Aconcagua Feb 09 '18 at 18:52
14

Slots are simple methods which can be public, protected, or private.

As Andrei pointed it out, signal are only a redefinition of protected, meaning they can only be emitted by the class in which they are defined.

If you want to make a class emit a signal from anoter one, you have to add it a public method (or slot) like this one:

void emitTheSignal(...) {
  emit theSignal(...);
}
gregseth
  • 12,952
  • 15
  • 63
  • 96
  • 6
    I think this does not answer the OP question. He's referring to signals that can only be listened to by the class that has defined them. – Daniel Jul 22 '11 at 19:33
  • "they can only be emitted by the class in which they are defined" ...Or a friend class. ;) – weberc2 Jun 24 '13 at 17:28
  • I'm not sure this is true. See here: http://stackoverflow.com/questions/19129133/qt-signals-and-slots-permissions The docs cay signals can be emitted from other classes, and are always public, not protected. – johnbakers Oct 02 '13 at 02:35
  • from `qobjectdefs.h` : `#define signals protected`, so no, signals aren't `public`. – gregseth Oct 02 '13 at 06:55
5

Nowadays you can use Q_SIGNAL macro and normal C++ access specifier:

protected:
  Q_SIGNAL void myProtectedSignal();

private:
  Q_SIGNAL void myPrivateSignal();
mip
  • 8,355
  • 6
  • 53
  • 72
4

Qt signals are public in the sense that any object can connect to any signal.

Kyle Lutz
  • 7,966
  • 2
  • 20
  • 23
  • 2
    they are also public in the sense that any other class may emit them, as they are public functions. this may have changed from prior versions of Qt. see here http://stackoverflow.com/questions/19129133/qt-signals-and-slots-permissions/19130567#19130567 – johnbakers Oct 02 '13 at 05:41
  • Object-oriented programming uses encapsulation to avoid access to internal method and data. In case signals are for internal purposes only they should be hidden, too. – Th. Thielemann Nov 09 '20 at 14:51
4

All the existing answers are incorrect.

A signal can be made private by adding a QPrivateSignal type to its definition as the last argument:

signals:
  
  void mySignal(QPrivateSignal);

QPrivateSignal is a private struct created in each QObject subclass by the Q_OBJECT macro, so you can only create QPrivateSignal objects in the current class.

Technically, the signal still has public visibility, but it can only be emitted by the class that created it.

Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97
1

You can use the PIMPL pattern for that. Your private signals exists in the private implementation only.

Th. Thielemann
  • 2,592
  • 1
  • 23
  • 38
  • Would not a PIMPL, derived from QObject, make it heavier and worsen the performance? – MasterAler Nov 08 '19 at 12:35
  • 2
    Yes, it takes some time. But consider the following questions: How many time does it cost to call a subroutine? Is the related program part performance relevant? – Th. Thielemann Nov 10 '19 at 17:21
  • Not sure why this was down voted. I use this approach successfully, for example for a state machine wrapper, which internally uses a QStateMachine but does not expose it (architectural reasons). Likewise, I don't want to expose the signals used to make the state machine do its transitions, as otherwise those signals would be mixed up with the public API signals, which would decrease maintainability. Since the state machine transitions on user interactions only, the performance impact is completely irrelevant in my case. – Tim Meyer Nov 09 '20 at 05:53