I am making an abstract-base-class and was thinking I might want a pure virtual signal. But when I compiled I get a warning for the pure virtual signals I have defined:
../FILE1.h:27: Warning: Signals cannot be declared virtual
../FILE1.h:28: Warning: Signals cannot be declared virtual
Is it valid to define a pure virtual signal in C++/Qt? Is it valid to define a virtual signal?
Qt's signal and slot documentation page says you can define virtual slots but doesn't talk about signals. I can't seem to find good information on pure virtual signals.
Given the above two statements here's my thinking:
Signals don't have an implementation but declaring it pure virtual will require the inheriting class to provide an implementation... which directly conflict with "signals don't have an implementation". It's like asking someone to be in two places at once it's just not possible.
So in conclusion it seems like declaring a "pure virtual" "signal" should be an error and thus not valid.
In the case of an abstract base class here's what I think is correct:
When one declares the function only "virtual" it still gives the warning. To avoid any warnings I think the solution is to not qualify the signal with any "virtual" or "pure virtual" and then the inheriting class will not declare any signals but can still emit the signals defined in the base class.
[1] when I say that "signals don't ever have an implementation" I mean that the person implementing the class doesn't provide the implementation. I understand that behind the scene Qt's moc provides an implementation in the moc_FILE1.cpp .
The warning is reported by moc, not by the C++ compiler, and it is valid except in the specific case of abstract interfaces.
The only valid use for virtual signals is when declaring abstract interfaces that don't derive from QObject
, as detailed in this excellent answer. There's nothing wrong with that approach. Moc tries to be helpful, since in most cases a virtual signal is a mistake.
Even then, the simple workaround for not getting the warning is to skip the signals:
keyword in the interface. It is completely unnecessary, since the interface doesn't derive from QObject
and thus shouldn't be processed by moc at all:
// https://github.com/KubaO/stackoverflown/tree/master/questions/virtual-slot-10029130
#include <QtCore>
class IDogInterface {
public:
// no signals: section since it's not a QObject!
virtual void barks() = 0; // a signal
};
class ADog : public QObject, public IDogInterface {
Q_OBJECT
public:
Q_SIGNAL void barks() override; // implementation is generated by moc
};
class Monitor : public QObject {
Q_OBJECT
int m_count{};
Q_SLOT void onBark() { m_count++; }
public:
int count() const { return m_count; }
void monitorBarks(IDogInterface * dog) {
QObject * dogObject = dynamic_cast<QObject*>(dog);
if (dogObject) {
connect(dogObject, SIGNAL(barks()), SLOT(onBark()));
} else {
qWarning() << "cannot monitor barking on dog instance" << (void*)dog;
}
}
};
int main() {
ADog dog;
Monitor monitor;
monitor.monitorBarks(&dog);
emit dog.barks();
Q_ASSERT(monitor.count() == 1);
}
#include "main.moc"
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