我想提出一个抽象基类和想我可能需要一个纯虚信号。 但是,当我整理我得到我所定义的纯虚信号的警告:
../FILE1.h:27: Warning: Signals cannot be declared virtual
../FILE1.h:28: Warning: Signals cannot be declared virtual
是有效,以限定在C ++ / Qt的纯虚信号? 它是有效的定义虚拟信号?
Qt的信号和槽文档页面说,你可以定义虚拟插槽,但不会谈论信号。 我似乎无法找到纯虚信号良好的信息。
- 信号不曾经有一个实现[1](即你在.h文件中定义的信号,然后有在的.cpp没有实现)。
- 声明一个函数纯虚拟的主要目的是迫使继承类提供一个实现。
鉴于以上两个语句这里是我的想法:
信号没有实现,但它声明纯虚需要继承类提供一个实现......这直接与“信号没有实现”相冲突。 这就像问一个人是在两个地方一次,它只是不可能的。
所以在最后,好像宣称“纯虚”,“信号”应该是一个错误,因而无效。
在这里抽象基类的情况下,就是我认为是正确的:
当一个声明函数只有“虚拟”它仍然给了警告。 为了避免任何警告我认为解决方案是不与任何“虚拟”或“纯虚”,然后将继承类将不声明任何信号,但仍然可以发出在基类中定义的信号限定信号。
[1]当我说“信号不曾经有一个实现”我的意思是实现类的人并没有提供实现。 据我所知,幕后Qt的MOC提供了moc_FILE1.cpp的实现。
该警告是由商务部报告,而不是由C ++编译器,它是除了在抽象接口的特定情况下有效。
虚拟信号的唯一有效使用是宣布不派生自抽象接口时QObject
,因为在这个优秀的答案详细 。 有什么不妥的做法。 莫克尝试是有益的,因为在大多数情况下,虚拟信号是一个错误。
即使这样,对于没有得到警告的简单的解决方法是跳过signals:
在界面中的关键字。 它是完全没有必要的,因为该接口不从派生QObject
并且因此不应该被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"
我认为有简单的有(纯)虚的信号是没有意义的。 该signals
提供给Qt的宏简单地扩展到protected
,所以你要声明的信号是实际的保护方法的声明。 所产生的代码moc
将提供的那些函数的实现。
有一种解决方案来创建将连接给定时隙的信号,或反之亦然纯虚函数。 例如:
class IBaseInterface
{
public:
virtual bool connectToSignal1(QObject* pReceiver, const char* pszSlot, bool bConnect) const = 0;
};
class CDerived : public QObject, public IBaseInterface
{
Q_OBJECT
public:
virtual bool connectToSignal1(QObject* pReceiver, const char* pszSlot, bool bConnect) const;
signals:
void signal1(const QString& msg);
};
bool CDerived::connectToSignal1(QObject* pReceiver, const char* pszSlot, bool bConnect) const
{
if(bConnect)
return connect(this, SIGNAL(signal1(QString)), pReciever, pszSlot);
return disconnect(this, SIGNAL(signal1(QString)), pReciever, pszSlot);
}
进一步在客户代码之一可以输入:
class CSomeClass : public QObject
{
Q_OBJECT
protected /*or public, or private*/ slots:
void someSlot(const QString& msg);
};
void CSomeClass::somefunction()
{
IBaseInterface* p = new CDerived;
if (!p->connectToSignal1(this, SLOT(someSlot(QString)), true))
QMessageBox::warning(this, tr("Warning"), tr("Cannot connect ...."), QMessageBox::Ok);
}