Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt signal-slot duplication code avoidance



  • I would like to share signals and possibly slot implementations among different classes, but it seems Qt does not allow this.

    Basically I would like to have something like:

    class CommonSignals
      {
      signals:
      void mysignal();
      };
    
    class A : 
        public QObject, 
        public CommonSignals
      {
        Q_OBJECT
      public:
        void doSomething()
          {
          emit mysignal();
          }
      };
    
    
    class B : 
        public QObject, 
        public CommonSignals
      {
        Q_OBJECT
    
      public:
    
        B()
          {
          connect(&a, &A::mysignal, this, &B::mysignal);
          }
    
        A a;
      };
    

    So that when for some reason A emits a signal B emits the same signal too. This to avoid useless code replication and improve maintainability. In other words the goal is to make B (or other classes) extend different classes, e.g. CommonSignals, CommonSignals2, CommonSignals3 etc so that you can use these CommonSignalsX for different applications withour re-writing the same code every time.

    Any ideas?

    PS I've tried also with virtual inheritance but I've got classical qmake problems



  • you made me confused about what you need - you can have many classes that emit the very same name signal (like readyread - in qtcpsocket, qabstractsocket, qudpsocket and so on...) but you make the difference between them when you use connect... - you have to select the sender.. so how can it be any confusions at all??
    please be a bit more specific...



  • @vernes
    Hi,
    I think in CommonSignals you lost Q_OBJECT macro



  • @CP71 said in Qt signal-slot duplication code avoidance:

    @vernes
    Hi,
    I think in CommonSignals you lost Q_OBJECT macro

    Yep, it's just pseudocode, just to give you an idea



  • @arsinte_andrei said in Qt signal-slot duplication code avoidance:

    you made me confused about what you need - you can have many classes that emit the very same name signal (like readyread - in qtcpsocket, qabstractsocket, qudpsocket and so on...) but you make the difference between them when you use connect... - you have to select the sender.. so how can it be any confusions at all??
    please be a bit more specific...

    I'm speaking about inheriting from classes. Qt seems having problems when you inherit from multiple classes.
    If that class B was extending CommonSignals and CommonSignals2, both of them containing signals and slots, I'm sure I would get compilation problems



  • @vernes
    QObject don't support multiple inheritances because of MOC. I suggest you to think in a hasA relationship instead of isA.

    Virtual inheritance with QObject is not supported.



  • @vernes why on earth will you have 2 different classes that are emitting the very same name signall for the very same thing? and to process the very same data at the very same time and both of them to be the inherited classes for the 3rd which is doing the very same thing?? it just doesn't make any sense at all - I've already explained to you how qsocket work.. and is processing signals from different classes that it inherited from I do not see where the confusion can be? I mean the signal slot connector in Qt is very mature and is doing a great job... there is no confusion even for the compiler this is why we have moc files - to avoid confusions...
    so your problem doesn't make any sense at least to me... I've done many classes that extend 2 or 3 classes without any problems in managing the signals from them - maybe had to reimplement some of the signals.. but that's the way it is.. you can have a look at Qt source... many times a class is not doing anything except putting together 2 classes



  • @KillerSmath said in Qt signal-slot duplication code avoidance:

    Virtual inheritance with QObject i

    Ok, I suspected that. I'm just trying to find the best solution to not repeat code.

    Basically, in my design, B is a class that contains different classes A, C, D, E, all of them that have different signals.
    B must just forward signals, My idea was to create signals in helper classes. E.g. ASignals, CSignals, DSignals, ESignals,
    and do something like A : public ASignals, C : public CSignals etc. B should then extend only one QObject and all the
    signals classes B: public QObject, ASignals, CSignals, DSignals, ESignals. Ideally I would like to do this same trick for slots.

    Is there a way to circumvent this virtual inheritance problem in this way?



  • @arsinte_andrei said in Qt signal-slot duplication code avoidance:

    @vernes why on earth will you have 2 different classes that are emitting the very same name signall for the very same thing? and to process the very same data at the very same time and both of them to be the inherited classes for the 3rd which is doing the very same thing?? it just doesn't make any sense at all - I've already explained to you how qsocket work.. and is processing signals from different classes that it inherited from I do not see where the confusion can be? I mean the signal slot connector in Qt is very mature and is doing a great job... there is no confusion even for the compiler this is why we have moc files - to avoid confusions...
    so your problem doesn't make any sense at least to me... I've done many classes that extend 2 or 3 classes without any problems in managing the signals from them - maybe had to reimplement some of the signals.. but that's the way it is.. you can have a look at Qt source... many times a class is not doing anything except putting together 2 classes

    It doesn't make sense if you don't know the context. I'm trying to managing complexity, using different QThreads. The class that is B is a class that has to manage all the signals coming from the threads, do some stuff, and re-emitting these signals. Why this? because of maintainability / modularity, that's now too long to explain.



  • @vernes

    You can implement a hasX (composition) relationship

    class A : public QObject // is QObject
    {
        Q_OBJECT
    public:
        A() {}
    signals:
        void mySignal();
    };
    
    class B : public QObject // is QObject
    {
        Q_OBJECT
    public:
        B(){}
    
    signals:
        void mySignal();
    };
    
    class C : public QObject // is QObject
    {
        Q_OBJECT
    
    public:
        C()
        {
            connect(this, &C::sendToA, &a, &A::mySignal);
            connect(this, &C::sendToB, &b, &B::mySignal);
    
            connect(&a, &A::mySignal, [](){qDebug() << "A signal emitted";});
            connect(&b, &B::mySignal, [](){qDebug() << "B signal emitted";});
        }
    
    signals:
        void sendToA();
        void sendToB();
    private:
        A a; // has A
        B b; // has B
    };
    


  • @KillerSmath said in Qt signal-slot duplication code avoidance:

    @vernes

    You can implement a hasX (composition) relationship

    class A : public QObject // is QObject
    {
        Q_OBJECT
    public:
        A() {}
    signals:
        void mySignal();
    };
    
    class B : public QObject // is QObject
    {
        Q_OBJECT
    public:
        B(){}
    
    signals:
        void mySignal();
    };
    
    class C : public QObject // is QObject
    {
        Q_OBJECT
    
    public:
        C()
        {
            connect(this, &C::sendToA, &a, &A::mySignal);
            connect(this, &C::sendToB, &b, &B::mySignal);
    
            connect(&a, &A::mySignal, [](){qDebug() << "A signal emitted";});
            connect(&b, &B::mySignal, [](){qDebug() << "B signal emitted";});
        }
    
    signals:
        void sendToA();
        void sendToB();
    private:
        A a; // has A
        B b; // has B
    };
    

    Thank you for the feedback. It's my current approach, but as I said I'm trying to remove duplicated code :)



  • @vernes
    Maybe I lost something! Or I don't understand your issue!
    You don’t need of inherit from multiple classes.

    If I have to do something like this I would do:

    class CommonSignals : public QObject
    {
    Q_OBJECT
    public:
    CommonSignals( QObject *parent = NULL);

    signals:
    void mysignal();
    

    };

    class A : public CommonSignals
    {
    Q_OBJECT
    public:
    A( QObject *parent = NULL )

    void doSomething()
    {
    	emit mysignal();
    }
    

    };

    class B : public CommonSignals
    {
    Q_OBJECT

    public:

    B(QObject *parent = NULL ) : CommonSignals(parent)
    {
      connect(&a, &A::mysignal, this, &B::mysignal);
    }
    
    A a;
    

    };

    Maybe I read too fast and don’t understand your issue or your code.
    Sorry



  • @CP71 said in Qt signal-slot duplication code avoidance:

    CommonSignals

    Thank you for your feedback. The goal is to make B use CommonSignals1, CommonSignals2, CommonSignals3 together in the same class

    Code example:

    class CommonSignalsA : public QObject
    {
    Q_OBJECT
    public:
    CommonSignalsA( QObject *parent = NULL);
    
    signals:
    void mysignal();
    };
    
    class CommonSignalsB : public QObject
    {
    Q_OBJECT
    public:
    CommonSignalsB( QObject *parent = NULL);
    
    signals:
    void mysignal2();
    };
    
    class A : public CommonSignalsA
    {
    Q_OBJECT
    public:
    A( QObject *parent = NULL )
    
    void doSomething()
    {
    	emit mysignal();
    }
    };
    
    class B : public CommonSignalsB
    {
    Q_OBJECT
    public:
    B( QObject *parent = NULL )
    
    void doSomething2()
    {
    	emit mysignal2();
    }
    };
    
    class C : public CommonSignalsA,  public CommonSignalsB
    {
    Q_OBJECT
    
    public:
    
    C(QObject *parent = NULL ) : CommonSignalsA(parent), CommonSignalsB(parent)
    {
      connect(&a, &A::mysignal, this, &C::mysignal);
    connect(&b, &B::mysignal2, this, &C::mysignal2);
    }
    
    A a;
    B b;
    };
    

    Basically, my question is: is it possible to create a CommonSignals that doesn't use QObject, or however making this work with same trick.. maybe passing QObject in same way.



  • @vernes
    One point i would like to talk about here.
    The Software engineering warns to use the minimum coupling while maximize the cohesion of class.

    Note: Inheritance is a 2 edged weapon, reusability is good but dependence is bad.

    If you decide to modify a class with a high dependency level, it can break the logic of some dependent class and it can be recursive.



  • @KillerSmath said in Qt signal-slot duplication code avoidance:

    @vernes
    One point i would like to talk about here.
    The Software engineering warns to use the minimum coupling while maximize the cohesion of class.

    Note: Inheritance is a 2 edged weapon, reusability is good but dependence is bad.

    If you decide to modify a class with a high dependency level, it can break the logic of some dependent class and it can be recursive.

    Good point here. However I would say that the approach I'm describing is much better compared to a lot of copy & paste.

    I'd avoid use inheritance but unfortunately Qt seems encouraging it.

    Problem is Qt and templates do not work well together, and many things like CRTP are not possible in many cases.


Log in to reply