Избегание дублирования кода в слоте Qt - PullRequest
1 голос
/ 09 апреля 2019

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

В основном я хотел бы иметь что-то вроде:

class CommonSignals
  {
  signals:
  void mysignal();
  };

class A : 
    public QObject, 
    public CommonSignals
  {
    Q_OBJECT
  public:
    void doSomething()
      {
      emit mysignal();
      }
  };


class B : 
    public QObject, 
    public CommonSignals
  {
    Q_OBJECT

  public:

    B()
      {
      connect(&a, &A::mysignal, this, &B::mysignal);
      }

    A a;
  };

Так что, когда по какой-то причине А излучает сигнал, B тоже излучает тот же сигнал. Это позволяет избежать бесполезной репликации кода и повысить удобство сопровождения.

Есть идеи?

PS Я пробовал также с виртуальным наследованием, но у меня классические проблемы с qmake

Ответы [ 2 ]

3 голосов
/ 09 апреля 2019

Вы не можете сделать это. QObject нельзя использовать с множественным наследованием нескольких QObject баз. Только первый унаследованный класс может быть QObject. См:

https://doc.qt.io/qt-5/moc.html#multiple-inheritance-requires-qobject-to-be-first

Поскольку вам нужно, чтобы оба базовых класса были QObject (CommonSignals обеспечивает сигналы, это должен быть QObject), вам не повезло. Здесь вы можете использовать только старые макросы:

#define COMMON_SIGNALS \
    void signal1(); \
    void signal2();

class A: public QObject
{
    Q_OBJECT

public:
    // ...

signals:
    COMMON_SIGNALS
};

class B: public QObject
{
    Q_OBJECT

public:
    // ...

signals:
    COMMON_SIGNALS
};

Основная проблема во всем этом заключается в том, что Qt использует moc для генерации базового кода для сигналов и слотов. Однако moc - это простой препроцессор, который не понимает большую часть C ++.

Вы можете использовать Verdigris, чтобы избавиться от moc:

https://github.com/woboq/verdigris

Это позволяет вам иметь шаблонные QObject классы, например. Я сам не пробовал и, таким образом, не знаю, допускает ли это множественное наследование. Может быть стоит посмотреть.

1 голос
/ 09 апреля 2019

Почему бы просто не перенести наследование из QObject из производных классов A и B в CommonSignals ...

class CommonSignals: public QObject {
  Q_OBJECT;
signals:
  void mysignal();
};

class A: public CommonSignals {
  Q_OBJECT;
public:
  void doSomething ()
    {
      emit mysignal();
    }
};

class B: public CommonSignals {
  Q_OBJECT;
public:
  B ()
    {
      connect(&a, &A::mysignal, this, &B::mysignal);
    }
  A a;
};

Это не сработает для вас?

...