Подтвердить что ты не робот

Виртуальный сигнал Qt?

Во время просмотра кода Qt С++ я натолкнулся на это:

class Foo
{
  Q_OBJECT

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

Теперь, сигналы Qt не могут иметь тело, поэтому я удивлен, что это даже компилируется (возможно, потому, что тело эффективно пуст). Я также не вижу смысла делать сигнал виртуальным, поскольку... он не может иметь тело, так как его можно переопределить?

Я что-то пропустил или это действительный запах кода?

4b9b3361

Ответ 1

Это выглядит вонючим ко мне.

Он действителен для объявления сигнала в базовом классе и затем испускает его из производного класса, например.

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

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

void MyDerived::doSomething()
{
    // ....
    emit somethingHappened();
}

Возможно, это то, что должно было сделать объявление в вопросе.

Ответ 2

Строго С++, говорящий нормально, компилируется, данный signal является макросом для protected, а Q_UNUSED - отличным от void. Но вы должны получить сообщение об ошибке при запуске moc, который точно создает реализацию методов, объявленных как сигналы.

Ответ 4

TL; DR: Я не знаю, что должен был делать код, но он ошибался (не просто пахнущий неправильно, он prima facie недействителен). Реализации сигналов всегда, которые должны быть сгенерированы moc. Тело сигнала должно быть удалено.

  • Для того, чтобы код работал, он должен делать все три: компилировать, получать moc и ссылку. Это правда, что ваш код компилируется - у компилятора С++ нет причин не делать этого. Но он не пройдет через 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.