Issue with C++ inheritance working with Slots and Signals



  • I have a QVBoxLayout I want to fill with multiple QFrame objects. The QFrame objects are programmatically created and arranged based on some arbitrary selection I set up in my application. But I'm finding I'm doing something wrong with Signals and slots.

    I wanted each of the QFrame objects to be generated from a common base class that looks like this:

    @#ifndef CBOXBASE_H
    #define CBOXBASE_H

    #include <QObject>
    class CboxBase : public QObject
    {
    Q_OBJECT
    public:
    explicit CboxBase(QObject *parent = 0);
    virtual void hideMyFrame();
    virtual void showMyFrame();
    signals:
    public slots:
    };

    #endif // CBOXBASE_H
    @

    I would then inherit this with something like this:

    @#ifndef CBOXXFORM_H
    #define CBOXXFORM_H
    #include "CboxBase.h"
    #include "CustomWidgets/nileexpander.h"

    class QFrame;
    class QFormLayout;
    class QLabel;
    class QDoubleSpinBox;
    class QVBoxLayout;
    class CboxXform : public CboxBase
    {
    private:
    QFrame *m_myFrame;
    QFormLayout *m_myLayout;
    NileExpander *m_expander;

    QLabel *m_labels[9];
    QDoubleSpinBox *m_fields[9];

    public:
    CboxXform(QVBoxLayout *_parentLayout, int _width);
    virtual void hideMyFrame();
    virtual void showMyFrame();

    signals:

    public slots:
    void vchange(double _value);

    private:
    void makeChannel(int _index, const QString &_label, QFont &_font);

    };

    #endif // CBOXXFORM_H'@

    I thought I could individualize my slot calls in my derived class. But when I run, I get this warning:

    @QObject::connect: No such slot CboxBase::vchange(double) in NodeGui/CboxXform.cpp:64
    QObject::connect: (sender name: 'fieldTranslatexX')@

    So its expecting my slot call to be in the base class--which is not what I want to do because the QFrames will all be different and have different requirements. How do I fix this?



  • Hi,
    try declaring the slot
    @virtual void vchange(double _value);@
    in the base class CboxBase.
    How do you create the inherited instances?
    And how do you connect the signals and slots?

    Greetings
    Nando



  • If I make it virtual, that does work. My only problem with this approach would be I would have a bunch of virtual functions in the base class that would only be relevant to a specific inheritance.

    While this approach seems doable, it does seem like a hack.

    I'm connecting the signals and slots like this (this just a test case, so it has flaws:

    @ connect(m_fields[_index],
    SIGNAL(valueChanged(double)),
    this,
    SLOT(vchange(double)))@



  • Ok, this seems to work. Rather than the base class being a QObject, just didn't have it inherit a QObject. It isn't necessary to inherit QObject because the base class is purely utilitarian and is common just so I can easily manage a bunch of these at the same time.

    But in my inherited class, I declared it like this:

    @class CboxXform : public QObject, CboxBase@

    Then the signals and slots are individualized to the specific class. This seems to work.



  • "If I make it virtual, that does work. My only problem with this approach would be I would have a bunch of virtual functions in the base class that would only be relevant to a specific inheritance. "
    I'm not a expertise in C++, but I think you should look a design pattern to solve this problem, inheritance maybe cause a maintenance problem for you in future. I guess isolating the method that varies would be a better approach. Someone with more experience could point out witch patter could be used for your case...


  • Qt Champions 2016

    Just a thought. Might be totally off :)
    Does your m_fields array have pointers to the base class ?
    So when you say connect this object , it thinks you mean the base object as
    there is no virtual function involved/anything that would have it resolve to the child. (CboxXform)
    if you tried (for test) to type case it to the correct class in the connect call?



  • You should avoid multi inheritance from QObject otherwise you might get in unpredictable trouble...

    I guess your problem is that you missed the Q_OBJECT macro for CboxXform so the moc does not generate the needed meta glue code to find the declared slots.

    Or you could try to use the new connect syntax, that should work with every method even if it's not declared as a slot:

    @
    connect(signalObject,
    &SignalClassName::signalName,
    slotObject,
    &SlotClassName::slotName)
    @



  • I will give these a try. I'm not a big fan of the multiple inheritance either.



  • [quote author="flandi" date="1412760724"]
    I guess your problem is that you missed the Q_OBJECT macro for CboxXform so the moc does not generate the needed meta glue code to find the declared slots.
    [/quote]

    I think flandi is right, in your original code just add the Q_OBJECT macro to the CboxXform and it should work.


  • Lifetime Qt Champion

    Hi,

    [quote author="flandi" date="1412760724"]You should avoid multi inheritance from QObject otherwise you might get in unpredictable trouble...
    [/quote]

    On the contrary, it's predictable: you can't inherit QObject multiple times. "Here":http://doc.qt.digia.com/qq/qq15-academic.html#multipleinheritance you have an interesting article on subject



  • The inherointance in the beginning is correct, but the Q_OBJECT macro is missing in the derived class. Having that, you will get the moc class and it should work :-)



  • I ended up up ditching the base class design. So I avoided the issue altogether (for now).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.