Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use SIGNAL and SLOT without deriving from QObject?

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.

like image 247
6e69636b6e616d65 Avatar asked Sep 21 '11 15:09

6e69636b6e616d65


People also ask

How do I connect Qt signals and slots?

To connect the signal to the slot, we use QObject::connect(). There are several ways to connect signal and slots. The first is to use function pointers: connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed);

Are signals and slots thread safe?

It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.


2 Answers

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);
}
like image 174
spraff Avatar answered Sep 21 '22 15:09

spraff


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.

like image 21
Jason Avatar answered Sep 21 '22 15:09

Jason