Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it valid to define a pure virtual signal in C++/Qt?

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.

like image 421
Trevor Boyd Smith Avatar asked Apr 05 '12 13:04

Trevor Boyd Smith


2 Answers

  • Signals don't ever have an implementation[1] (i.e. you define the signal in your .h file and then there is no implementation in the .cpp).
  • The main purpose of declaring a function pure virtual is to force the inheriting class to provide an implementation.

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 .

like image 200
Trevor Boyd Smith Avatar answered Nov 20 '22 01:11

Trevor Boyd Smith


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"
like image 7
Kuba hasn't forgotten Monica Avatar answered Nov 20 '22 01:11

Kuba hasn't forgotten Monica