How to use SIGNAL and SLOT without deriving from QObject?

20,785

Solution 1

If you want a copyable object with QObject features you need membership (by pointer) rather than inheritence.

You can derive a class Handler from QObject where Handler's slots call SomeInterface virtual functions on its parent.

struct NonQObjectHandler {
    virtual ~ NonQObjectHandler () {}
    virtual void receive (int, float) = 0;
};

class Handler : public NonQObjectHandler {
    struct Receiver;
    std :: unique_ptr <Receiver> m_receiver;
    void receive (int, float); // NonQObjectHandler
public:
    Handler ();
    Handler (const Handler &); // This is what you're really after
};

class Handler :: Receiver : public QObject {
Q_OBJECT
private:
    NonQObjectHandler * m_handler;
private slots:
    void receive (int, float); // Calls m_handler's receive
public:
    Receiver (NonQObjectHandler *);
};

Handler :: Handler ()
: m_receiver (new Receiver (this))
{
}

Handler :: Handler (const Handler & old)
: m_receiver (new Receiver (this))
{
    // Copy over any extra state variables also, but
    // Receiver is created anew.
}

Handler :: Receiver :: Receiver (NonQObjectHandler * h)
: m_handler (h)
{
    connect (foo, SIGNAL (bar (int, float)), this, SLOT (receive (int, float)));
}

void Handler :: Receiver :: receive (int i, float f)
{
    m_handler -> receive (i, f);
}

Solution 2

If you want to implement event-driven functionality using a signals/slots pattern, but do not want to work inside the confines of Qt (i.e., you want to use your class inside of STL containers, etc. that require copy-constructors), I would suggest using Boost::signal.

Otherwise, no, you can't possibly do what you're wanting without deriving from QObject since that base class is what handles the Qt runtime signals/slots functionality.

Solution 3

You cannot use Qt's signal/slot mechanisms without using QObject/Q_OBJECT.

You theoretically could create a dummy QObject and compose it into your class. The dummy would then forward the slot calls to your class. You will probably run in to issues with lifetime management, for the reasons that Liz has described in her comment.

Solution 4

Since Qt5 you can just connect to any function

connect(&timer, &QTimer::finished,
        &instanceOfMyClass, &MyClass::fancyMemberFunction);
Share:
20,785
6e69636b6e616d65
Author by

6e69636b6e616d65

Updated on July 30, 2022

Comments

  • 6e69636b6e616d65
    6e69636b6e616d65 almost 2 years

    OR other way to formulate my question (though it didn't solve my problem): 'QObject::QObject' cannot access private member declared in class 'QObject'

    I need SIGNALs and SLOTS functionality in my class, but I assume it is not possible without to derive from QObject?

    class MyClass
    {
    signals:
       importantSignal();
    public slots:
       importantSlot();
    };
    

    The Problem seems to be that I need to derive from QObject to use signals and slots ... but I need the default contructor of MyClass. But I can't construct them because of the following feature of QObject: No Copy Constructor or Assignment Operator.

    I tried a lot ...

    So my shoul Class look like that:

    #include <QObject>
    class MyClass: public QObject
    {
        Q_OBJECT
    public:
        explicit MyClass(QObject *parent = 0); //autogenerated by qtcreator for QObject derived class
        MyClass(const MyClass * other);
    
    signals:
        importantSignal();
    public slots:
        importantSlot();
    };
    

    I need the default contructor of MyClass.

    So is there any possibility do avoid the "'QObject::QObject' cannot access private member declared in class 'QObject'" error?

    Or as an alternative is there any possibility to use signals and slots without QObject?

    I'm glad for any advice.

  • 6e69636b6e616d65
    6e69636b6e616d65 over 12 years
    mh... nice advice, but i like to work on with Qt. To late to use another lib. but thx.
  • 6e69636b6e616d65
    6e69636b6e616d65 over 12 years
    so is there a way to avoid that "'QObject::QObject' cannot access private member declared in class 'QObject'"-error?
  • Jason
    Jason over 12 years
    Yes ... don't do something that requires a copy-constructor or assignment operator. This basically means that it's often a good choice to work with objects derived from QObject through pointers rather than instances that may need copying to move around. It's not that you can't use instances, but you can't copy them, and therefore you also can't stick them in STL containers, etc.
  • 6e69636b6e616d65
    6e69636b6e616d65 over 12 years
    you may give an example/snippet?
  • Ph0t0n
    Ph0t0n about 6 years
    You can use connect() without Q_OBJECT. But you won't be able to use emit without Q_OBJECT.
  • scopchanov
    scopchanov about 5 years
    Does this work when MyClass does not derive from QObject?
  • ManuelSchneid3r
    ManuelSchneid3r about 5 years
    No, but then you can omit the receiver (3rd arg) and use static funcions or std::bind/lambdas to bind the object and member function to a callable.