I have a base class, which defines a Qt slot
class Base
{
public:
Base()
{
connect(otherobject, SIGNAL(mySignal), this, SLOT(mySlot));
}
public slots:
virtual void mySlot()
{}
}
Subclass A just implements some other stuff. Subclass B overrides the slot
class SubB : Base
{
public:
SubB() : Base()
{
// Necessary?
connect(otherobject, SIGNAL(mySignal), this, SLOT(mySlot));
}
public slots:
virtual void mySlot() override
{}
}
Does the override of the slot also replace the connection, which was done before in the Bass constructor (I.e. The connect in SubB would be unnecessary)?
Yes, just like regular c++ pure virtual methods. The code generated by MOC does call the pure virtual slots, but that's ok since the base class can't be instantiated anyway... Again, just like regular c++ pure virtual methods, the class cannot be instantiated until the methods are given an implementation.
Slots are a Qt-specific extension of C++. It only compiles after sending the code through Qt's preprocessor, the Meta-Object Compiler (moc). See http://doc.qt.io/qt-5/moc.html for documentation.
In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal.
It gets better: you don't need any special treatment for the slot in the derived class. There's no need to make it virtual (it already is per C++ semantics), and there's no need to make it a slot again (it already is per Qt semantics). It is incorrect to add the second connection in Derived
, it'll simply result in the slot being activated twice per every activation of the signal.
Remember that signals and slots are regular C++ methods, and that slots are invoked from machine-generated code that looks exactly as if you called the slot without specifying the particular class it should be in. Thus a virtual slot acts as you think it should, given the semantics of C++.
The below is sufficient:
class Base : public QObject
{
Q_OBJECT
public:
Base(QObject * src, QObject * parent = 0) : QObject(parent)
{ connect(src, SIGNAL(mySignal), SLOT(mySlot)); }
Q_SLOT virtual void mySlot() {}
};
class Derived : public Base
{
Q_OBJECT
public:
Derived(QObject * src, QObject * parent = 0) : Base(src, parent) {}
void mySlot() Q_DECL_OVERRIDE { ... }
};
You don't need to put the same connect
in the subclass constructor. When a SubB
object is created, the connect
in the Base
constructor will connect the right slot (the one overridden in SubB).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With