在C++/Qt中定义纯虚拟信号是否有效?

Tre*_*ith 14 c++ qt abstract-class signals-slots

我正在制作一个抽象基类,并且认为我可能 想要一个纯粹的虚拟信号.但是当我编译时,我得到了我已经定义的纯虚拟信号的警告:

../FILE1.h:27: Warning: Signals cannot be declared virtual
../FILE1.h:28: Warning: Signals cannot be declared virtual
Run Code Online (Sandbox Code Playgroud)

在C++/Qt中定义纯虚拟信号是否有效?定义虚拟信号有效吗?

Qt的信号和插槽文档页面说明你可以定义虚拟插槽,但不会谈论信号.我似乎无法找到关于纯虚拟信号的好信息.

Tre*_*ith 9

  • 信号没有实现[1](即你在.h文件中定义信号,然后在.cpp中没有实现).
  • 声明一个纯虚函数的主要目的是强制继承类提供一个实现.

鉴于以上两个陈述,我的想法是:

信号没有实现,但声明它是纯虚拟将需要继承类提供实现......这与"信号没有实现"直接冲突.这就像是要求某人同时在两个地方,这是不可能的.

因此,总的来说,似乎声明"纯虚拟""信号"应该是一个错误,因此无效.


在抽象基类的情况下,我认为这是正确的:

当一个人声明该功能只是"虚拟"时,它仍会发出警告.为了避免任何警告,我认为解决方案是不使用任何"虚拟"或"纯虚拟"来限定信号,然后继承类不会声明任何信号,但仍然可以发出基类中定义的信号.

[1]当我说"信号没有实现"时,我的意思是实现该类的人不提供实现.据我所知,在场景背后,Qt的moc在moc_FILE1.cpp中提供了一个实现.


Rei*_*ica 6

警告由moc报告,而不是由C++编译器报告,除了抽象接口的特定情况外,它是有效的.

虚拟信号的唯一有效使用是宣布不派生自抽象接口时QObject,因为在这个优秀的答案详细.这种方法没有错.Moc试图提供帮助,因为在大多数情况下,虚拟信号是错误的.

即使这样,没有收到警告的简单解决方法是跳过signals:界面中的关键字.这是完全没必要的,因为接口不是从QObjectmoc 派生的,因此根本不应该由moc处理:

// 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"
Run Code Online (Sandbox Code Playgroud)