虚拟Qt信号?

18

我在审核一些Qt C++代码时发现了这个:

class Foo
{
  Q_OBJECT

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

现在,Qt信号不能有函数体,所以我很惊讶这个代码甚至可以编译通过(也许是因为函数体实际上是空的)。我还看不出将信号定义为虚函数的意义在哪里,因为它没有函数体,那么如何重写它呢?

我是否遗漏了什么,或者这是一种有效的代码坏味道?

4个回答

22

我感觉那看起来有点臭。

在基类中声明一个信号,然后从派生类中发射它是有效的,例如:

class MyBase : public QObject
{
    Q_OBJECT
// ...
signals:
    void somethingHappened();
};

class MyDerived : public MyBase
{
    Q_OBJECT
// ...
    void doSomething();
};

void MyDerived::doSomething()
{
    // ....
    emit somethingHappened();
}
也许这就是问题中声明所要达到的目的。

4

严格来说,如果signal是一个宏定义为protected,而Q_UNUSED是一个转换为void的类型,则编译通过是正常的。但是,在运行moc时应该会出现错误,因为它精确地创建了作为信号声明的方法的实现。


2
它可能会编译,但仍然存在ODR违规:该函数有两个主体,一个在头文件中,另一个在由moc发出的cpp中。 - Yakov Galka

3

2
TL;DR: 我不知道这段代码的目的是什么,但它是错误的(不仅仅是看起来错误,而且是显然无效的)。Signal实现应该 总是 由 moc 生成。Signal的主体应该被移除。
  1. For the code to work, it should do all three: compile, get past moc, and link. It is true that your code does compile - the C++ compiler has no reason not to. But it won't pass through moc nor will it link.

  2. Although perhaps moc didn't detect some of it back in 2010, here's how moc acts today:

    a) moc doesn't allow signal definitions in class bodies, with the diagnostic Error: Not a signal declaration. So class X { Q_SIGNAL void s() {} }; triggers it, but class X { Q_SIGNAL void s(); }; void X::s() {} won't.

    b) moc doesn't allow a Q_OBJECT macro in a class not deriving from QObject, with the diagnostic Error: Class contains Q_OBJECT macro but does not inherit from QObject.

  3. Since it doesn't make any sense to talk about signals in classes that don't derive from QObject, let's assume that the code really looked as follows:

    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);
    }
    

    This will get past moc and will compile, but it won't link. The linker will issue a diagnostic for multiple declaration of Foo::someSignal. There's one definition in this file, and another in the moc-generated source.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接