State of QPrivateSignal
-
Hi!
I'd like to know what is the status of
QPrivateSignal
in modern Qt.
Is its usage recommended and does it perform its function as expected?As far as I can see, there isn't any documentation in Signals & Slots page, nor
QObject
, norQMetaObject
docs.I could only find a forum post from 2021 about how
QPrivateSignal
can be sidestepped making the signal still be publicly callable.I really like the idea of making signals emittable only from inside the class, meaning that all signals called are absolutely intended by the class, leaving no chance of someone abusing them, but the lack of documentation makes me want to avoid using them.
-
The above is needlessly complicated.
If Outer owns Helper, connect Helper::helperSignal to Outer::onHelperSignal and is the one calling Helper::helperSignal, that's a lot of indirection over calling onHelperSignal directly.
@Sakars Don't use QPrivateSignal, relying on the convention that you shouldn't emit a signal that's not yours should be enough unless you have a specific scenario you want to avoid. Code can be abused with or without that.
-
No documentation = not for public use = don't blame anyone if you use it but it breaks your code in the future.
-
@Sakars I would not recommend inheriting private from QObject. There are a couple of mechanisms that rely on public function access.
But you could make a helper class with signals only. Make that a private/protected member instance of your class and use that for your "private" signals/connects
-
@J-Hilk Inheriting from QObject privately hadn't even crossed my mind as an option and it's not something I want/need to do.
But you could make a helper class with signals only. Make that a private/protected member instance of your class and use that for your "private" signals/connects
Interesting... How would this look in-code? A const getter method on the class, that returns a const ref to the member helper class instance to provide access for connecting signals? Can you not emit a member signal from a const ref?
I assume this helper class would also have to inherit from QObject, is that correct? -
#include <QObject> #include <QDebug> // Helper class with only signals, inaccessible from outside class Helper : public QObject { Q_OBJECT public: explicit Helper(QObject *parent = nullptr) : QObject(parent) {} signals: void helperSignal(); // Internal signal only accessible by Outer }; // Outer class that owns and controls the helper instance class Outer : public QObject { Q_OBJECT public: explicit Outer(QObject *parent = nullptr) : QObject(parent), m_helper(new Helper(this)) { // Connect the helper signal to a slot in this class connect(m_helper, &Helper::helperSignal, this, &Outer::onHelperSignal); } protected: // Internal function to trigger the helper's signal void emitHelperSignal() { emit m_helper->helperSignal(); } private slots: void onHelperSignal() { qDebug() << "Outer: Received helper signal!"; } private: Helper *m_helper; // Private helper instance }; // Main function to test the setup int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Outer outer; // The signal is fully encapsulated. Only the Outer class can trigger it. outer.emitHelperSignal(); // Testing encapsulation return app.exec(); } #include "main.moc"
Caution, AI generated code
-
The above is needlessly complicated.
If Outer owns Helper, connect Helper::helperSignal to Outer::onHelperSignal and is the one calling Helper::helperSignal, that's a lot of indirection over calling onHelperSignal directly.
@Sakars Don't use QPrivateSignal, relying on the convention that you shouldn't emit a signal that's not yours should be enough unless you have a specific scenario you want to avoid. Code can be abused with or without that.
-
@GrecKo said in State of QPrivateSignal:
The above is needlessly complicated.
If Outer owns Helper, connect Helper::helperSignal to Outer::onHelperSignal and is the one calling Helper::helperSignal, that's a lot of indirection over calling onHelperSignal directly.
of course it is, but thats beside the point op, wanted a solution for "private" signals without using "QPrivateSignal" and I spouted ideas.
There are days when I like to delve into the rabbit hole :D
-
That's not what's requested though. A private signal is a signal that you can't emit from outside but can still connect to.
-
Don't use QPrivateSignal, relying on the convention that you shouldn't emit a signal that's not yours should be enough unless you have a specific scenario you want to avoid. Code can be abused with or without that.
As it is with ageing projects with multiple people coming and going, some new to Qt, relying on that people will keep abiding by convention isn't always enough. I know it's futile, but seeing as the project I'm working on already breaks this convention, I'm trying to find if there's some ways to at least improve the maintainability and somewhat future-proof at least some signals.
-
@J-Hilk Then I don't think this fits my ideal solution. Ideally a private/protected signal would have these properties:
- Any arbitrary class can connect to this signal without asking for "consent" from the class itself (i.e. you should be able to connect to it even if all you have is a constant reference to the instance)
- Any arbitrary class cannot emit the signal of this class directly even if they have a mutable reference to it.
- The class instance can emit its own (or any other instance of this class') signal the same way you can call a protected/private method.
-
ok,
finemake your own private signal than:
class MyClass : public QObject{ Q_OBJECT struct PrivatSignal{}; public: MyClass(QObject*parent = nullptr) : QObject(parent) {} signals: void myPrivateSignal(PrivatSignal); // == to void argument signal };
-
-
@Sakars said in State of QPrivateSignal:
Are there any documented alternatives to making signals only private/protected-ly emittable?
I don't understand the struggle :)
Event the suggested solutions here seem like overkill...private: Q_SIGNAL void privateSignal();
Done.
// works in Foo.cpp emit this->privateSignal();
// not in class = does not work Foo foo; emit foo->privateSignal();
Latter throws:
\main.cpp:42: Error: 'privateSignal' is a private member of 'Foo'
-
@Pl45m4 said in State of QPrivateSignal:
I don't understand the struggle :)
Event the suggested solutions here seem like overkill...It's not possible to connect to your private Q_SIGNAL from outside of the class. That's the requirement.
-
This post is deleted!