External code emitting my Qt signal: is QPrivateSignal the right guard for a public signals section?
0 reputation · 29 Apr 2024, 11:11 UTC
Problem
I have a QObject-derived class whose signals should only be emitted by the class itself, but since the signals macro expands to public in Qt 5 and later, any code that can see the header can call emit mySignal(). I want to prevent accidental external emission at compile time without breaking existing connect() calls from other objects.
What I understand so far
The documented idiom is to declare a nested struct QPrivateSignal {}; in the private section and add a defaulted QPrivateSignal* parameter to each signal, so only the class itself can construct the argument and therefore emit it. External connects should still work because connection does not require constructing that type.
Open questions
What is unclear to me is the actual boundary this creates:
- Does QPrivateSignal block emission through all call paths, or can string-based
SIGNAL()connects andQMetaObject::invokeMethodstill trigger the signal at runtime regardless of the extra parameter? - Are there side effects on moc-generated code, signal signatures in the meta-object system, or existing functor-based connects when I add the extra defaulted parameter to a signal that is already in use?
- Is there any supported way to make a
private slots:member truly unreachable via the meta-object system, or is C++ access control simply not enforced there?
Target is Qt 5.15 / Qt 6 with the new-style connect syntax.