#c #qt #inheritance #signals-slots #qobject
#c #qt #наследование #сигналы-слоты #qobject
Вопрос:
Я хотел бы поделиться сигналами и, возможно, реализациями слотов между разными классами, но, похоже, 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(amp;a, amp;A::mysignal, this, amp;B::mysignal);
}
A a;
};
Так что, когда по какой-то причине A испускает сигнал, B тоже испускает тот же сигнал. Это позволяет избежать бесполезной репликации кода и улучшить удобство обслуживания.
Есть идеи?
PS Я пробовал также с виртуальным наследованием, но у меня классические проблемы с qmake
Комментарии:
1. У вас опечатка:
connect(amp;a, amp;A::mysignal, this, amp;B::mysignal);
исправит вашу ошибку.2. Я отредактировал вопрос, поверьте мне, проблема была не в этом 🙂
3.
CommonSignals
не наследуетQObject
и поэтому не может иметь сигналов, связанных с ним. Вы не видите никаких ошибок или предупреждающих сообщений отmoc
?4. @Jarod42 Вы можете подключить сигнал к другому сигналу, это нормально.
5. @G.M. При множественном наследовании только одному из базовых классов разрешено быть a
QObject
. ТакCommonSignals
что не может быть одного. Это означает, что он не может использовать сигналы.
Ответ №1:
Вы не можете этого сделать. QObject
не может использоваться с множественным наследованием нескольких QObject
баз. Только первый унаследованный класс может быть a QObject
. См.:
https://doc.qt.io/qt-5/moc.html#multiple-inheritance-requires-qobject-to-be-first
Поскольку вам нужно, чтобы оба базовых класса были a QObject
( CommonSignals
предоставляет сигналы, это должно быть a 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. Спасибо за отзыв. Я ищу какое-то обходное решение, потому что я не хотел использовать макросы, кто знает, может быть, есть какой-то трюк, эхе
2. как насчет использования CRTP в некотором роде?
3. @Saturnu Проблема в moc. Он не понимает шаблоны. На самом деле, он не понимает большую часть C . Он просто ищет несколько простых вещей в файлах заголовков. Вы можете попробовать и использовать это, хотя это полностью избавляет от moc: github.com/woboq/verdigris
4. Да, я слышал о Verdigris, спасибо. Возможно, я попробую это в будущем, но я все еще заинтересован в поиске решения этой проблемы. В некоторых случаях мне удалось заставить шаблоны и Qt работать вместе 😉
Ответ №2:
Почему бы просто не перенести наследование из 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(amp;a, amp;A::mysignal, this, amp;B::mysignal);
}
A a;
};
Это не сработает для вас?
Комментарии:
1. Это не позволило бы вам создать, скажем, QLineEdit (или любой другой
QObject
класс, не производный напрямуюQObject
), который предоставляет общие сигналы. Я предполагаю, что это то, что имеет в виду OP.2. Спасибо за отзыв. Нет, я думаю, это решение не подходит. Цель на самом деле состоит в том, чтобы заставить B расширять другие классы, например, CommonSignals2, CommonSignals3 и т. Д. Как @NikosC. Я не думаю, что это должно работать во всех случаях.
3. ОК. Наверное, я неправильно понял вопрос.