在查看一些Qt C ++代码时,我遇到了这个问题:
class Foo
{
Q_OBJECT
signals:
virtual void someSignal(const QString& str, int n)
{
Q_UNUSED(str);
Q_UNUSED(n);
}
...
};
现在,Qt信号不能有一个身体所以我很惊讶这甚至编译(也许是因为身体实际上是空的)。我也没有看到将信号虚拟为......它不能有一个身体所以它怎么能被覆盖呢?
我在这里遗漏了什么或者这是一个有效的代码味道吗?
答案 0 :(得分:17)
这看起来很臭我。
在基类中声明一个信号然后从派生类中发出它是有效的,例如
class MyBase : public QObject
{
Q_OBJECT
// ...
signals:
void somethingHappened();
};
class MyDerived : public MyBase
{
Q_OBJECT
// ...
void doSomething();
};
void MyDerived::doSomething()
{
// ....
emit somethingHappened();
}
也许这就是问题中的声明要达到的目的。
答案 1 :(得分:4)
严格来说C ++说它是正常的,因为signal
是protected
的一个宏而Q_UNUSED
是void
的强制转换。
但是在运行moc
时会出错,这会精确地创建声明为信号的方法的实现。
答案 2 :(得分:3)
Qt信号不允许(纯)虚拟。请参阅此错误的评论 - https://bugreports.qt.io/browse/QTBUG-41004
答案 3 :(得分:2)
TL; DR:我不知道代码的意图是什么,但这是错误的(不仅仅是闻错了,它表面上看起来无效)。信号实现始终意味着由moc生成。应该删除信号的主体。
要使代码生效,它应该完成所有三项:编译,过去moc和链接。你的代码确实编译了 - C ++编译器没有理由不这样做。但它不会通过moc,也不会链接。
虽然可能 moc 在2010年没有发现其中的一部分,但今天 moc 的行为如下:
a) moc 不允许使用诊断Error: Not a signal declaration
的类体中的信号定义。因此class X { Q_SIGNAL void s() {} };
会触发它,但class X { Q_SIGNAL void s(); }; void X::s() {}
不会触发它。
b) moc 不允许某个类中的Q_OBJECT
宏不是来自QObject
,而是Error: Class contains Q_OBJECT macro but does not inherit from QObject
。
由于谈论不是从QObject
派生的类中的信号没有任何意义,让我们假设代码看起来真的如下:
class Foo : public QObject
{
Q_OBJECT
signals:
virtual void someSignal(const QString&, int);
};
void Foo::someSignal(const QString& str, int n)
{
Q_UNUSED(str);
Q_UNUSED(n);
}
这将通过moc并将编译,但它不会链接。链接器将为Foo::someSignal
的多个声明发出诊断。这个文件中有一个定义,而moc生成的源中有另一个定义。