虚拟Qt信号?

时间:2010-09-08 12:38:14

标签: c++ qt

在查看一些Qt C ++代码时,我遇到了这个问题:

class Foo
{
  Q_OBJECT

signals:
  virtual void someSignal(const QString& str, int n)
  {
    Q_UNUSED(str);
    Q_UNUSED(n);
  }
  ...
};

现在,Qt信号不能有一个身体所以我很惊讶这甚至编译(也许是因为身体实际上是空的)。我也没有看到将信号虚拟为......它不能有一个身体所以它怎么能被覆盖呢?

我在这里遗漏了什么或者这是一个有效的代码味道吗?

4 个答案:

答案 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 ++说它是正常的,因为signalprotected的一个宏而Q_UNUSEDvoid的强制转换。 但是在运行moc时会出错,这会精确地创建声明为信号的方法的实现。

答案 2 :(得分:3)

Qt信号不允许(纯)虚拟。请参阅此错误的评论 - https://bugreports.qt.io/browse/QTBUG-41004

答案 3 :(得分:2)

TL; DR:我不知道代码的意图是什么,但这是错误的(不仅仅是闻错了,它表面上看起来无效)。信号实现始终意味着由moc生成。应该删除信号的主体。

  1. 要使代码生效,它应该完成所有三项:编译,过去moc和链接。你的代码确实编译了 - C ++编译器没有理由不这样做。但它不会通过moc,也不会链接。

  2. 虽然可能 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

    < / LI>
  3. 由于谈论不是从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生成的源中有另一个定义。