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

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

16 голосов
/ 08 сентября 2010

При просмотре кода Qt C ++ я наткнулся на это:

class Foo
{
  Q_OBJECT

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

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

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

Ответы [ 4 ]

17 голосов
/ 08 сентября 2010

Мне это кажется вонючим.

Допустимо объявить сигнал в базовом классе и затем выдать его из производного класса, например,

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

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

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

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

4 голосов
/ 09 сентября 2010

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

3 голосов
/ 13 января 2015

Сигналы Qt не могут быть (чисто) виртуальными. См. Комментарии к этой ошибке - https://bugreports.qt.io/browse/QTBUG-41004

2 голосов
/ 20 августа 2015

TL; DR: я не знаю, для чего предназначался код, но это неправильно (не просто пахнет неправильно, это недействительно prima facie).Реализации сигнала всегда предназначены для генерации 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.

  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, - другое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...