Russian Qt Forum

Qt => Вопросы новичков => Тема начата: MaxoBik от Июль 23, 2015, 15:13



Название: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: MaxoBik от Июль 23, 2015, 15:13
Доброго времени суток.
Есть некий класс(SignalEmiter), унаследованный от QObject, выдающий сигналы. На эти сигналы нужно подписываться в других классах(их много), унаследованных от QObject(на самом деле некоторые из них наследуют от QWidget, но по иерархии классов все равно QObject). Так вот, что бы в каждом из этих классах не печатать что типа такого:
Код:
     void setSignalEmiter(SignalEmiter* semiter){
       if(m_semiter!=NULL){
         /* тут отписываемся от сигналов */
       }
       m_semiter = semiter;
       if(m_semiter!=NULL){
         /* тут подписываемся на сигналы */
       }
    }
protected:
    SignalEmiter* m_semiter;

Я решил использовать базовый класс, от которого должны были наследовать потребители сообщений SignalEmiter:
Код:
class SignalEmiterConsumer : QObject {
    Q_OBJECT
public:
    explicit SignalEmiterConsumer(QObject *parent=0) :
             QObject(parent),
             m_semiter(NULL)
    {
    }
    virtual SignalEmiter* getSignalEmiter(){
        return m_semiter;
    }

    void setSignalEmiter(SignalEmiter* semiter){
       if(m_semiter!=NULL){
         /* тут отписываемся от сигналов */
       }
       m_semiter = semiter;
       if(m_semiter!=NULL){
         /* тут подписываемся на сигналы */
       }
    }
 
protected slots:
    virtual void someSlot1(const QString &location, int exponent)=0;
     ....
    virtual void someSlotN(const QString &location, some_structure* kNumber, int tkNumber)=0;
protected:
     SignalEmiter* m_semiter;
};

Но проблема в том, что как я писал раньше, классы потребители сообщений уже наследуют от QObject, а QObject не позволяет множественное наследования.
Я даже хотел отказаться использовать в базовом классе SignalEmiterConsumer от QObject-а, и подписывания на сигналы с использованием адресов функций вместо слотов(в стиле Qt5), но как оказалось это тоже не возможно - нужно чтобы было наследования от QObject-а, иначе компилятор ругается.
Подскажите - как выполнить поставленную задачу?


Название: Re: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: Igors от Июль 23, 2015, 15:46
Через кросс-приведение, напр
Код
C++ (Qt)
class SignalEmiterConsumer  {
public:
   void setSignalEmiter(SignalEmiter* semiter){
      if(m_semiter!=NULL){
        /* тут отписываемся от сигналов */
      }
      m_semiter = semiter;
      if(m_semiter!=NULL){
        /* тут подписываемся на сигналы */
        QObject * dst = dynamic_cast <QObject *> (this);
        Q_ASSERT(dst);
        QObject::connect(semitter, .., dst, ..);
        ...  
      }
   }
Подразумеваетcя что SignalEmiterConsumer долит множественным наследованием к наследнику QObject. Хотя нужно ли это все? Почему бы не сделать под/от писки просто ф-циями?


Название: Re: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: MaxoBik от Июль 23, 2015, 16:04
Да, я так уже пробовал, но начинаются проблемы - говорит не возможности привести к QObject *, пробовал и через  reinterpret_cast с таким же результатом:

Цитировать
'QObject::connect' : none of the 4 overloads could convert all the argument types


т.е.:
Код:
QObject * dst = dynamic_cast <QObject *> (this);
QObject::connect( semitter, &SignalEmiter::someSignal1, dst, &SignalEmiterConsumer::someSlot1 );
ПС сигнатуры слота и сигнала совпадают. Скорей всего проблема в последнем аргументе, но как тут его правильно привести?
Еще пытался и вот так(также SignalEmiterConsumer не наследует от QObject):
Код:

QObject::connect( semitter, &SignalEmiter::someSignal1, &SignalEmiterConsumer::someSlot1 );
Пишут же в Qt5 можно указать просто адрес с функции с совпадающей сигнатурой к сигналу, но у меня такая же ошибка:
Цитировать
'QObject::connect' : none of the 4 overloads could convert all the argument types


Название: Re: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: Bepec от Июль 23, 2015, 16:16
Чисто для информации: в Qt 5+ можно привязывать сигналы к обычным функциям. И оно работает спокойно и без затрат.

PS сам размышлял над данной темой, пришёл к выводу, что придётся использовать предсборочный анализ и добавление нужного функционала в классы. (Ну т.е. прога перед началом сборки будет добавлять этот дублирующийся кусок во все классы и/или по условию) :)


Название: Re: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: MaxoBik от Июль 23, 2015, 16:31
Чисто для информации: в Qt 5+ можно привязывать сигналы к обычным функциям. И оно работает спокойно и без затрат.

Да вот что-то не выходит, может нужно какие заголовки включать или в .pro что-то добавлять?
Ошибка в QtCore\qobject.h у меня:

Код:
    //connect to a function pointer  (not a member)
    template <typename Func1, typename Func2>
    static inline typename QtPrivate::QEnableIf<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0, QMetaObject::Connection>::Type
            connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
    {
        return connect(sender, signal, sender, slot, Qt::DirectConnection); // <--- вот тут [b]'QObject::connect' : none of the 4 overloads could convert all the argument types[/b]
    }

Судя по всему он ищет ссылку на функцию в sender-е, а она у меня в другом классе.


Название: Re: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: Igors от Июль 23, 2015, 16:47
Цитировать
'QObject::connect' : none of the 4 overloads could convert all the argument types


т.е.:
Код:
QObject * dst = dynamic_cast <QObject *> (this);
QObject::connect( semitter, &SignalEmiter::someSignal1, dst, &SignalEmiterConsumer::someSlot1 );
При таком раскладе SignalEmiterConsumer не может иметь слотов - он ведь не QObject. Ну это и не нужно (хотя это часто хотят иметь :)). Но можно связывать "в старом стиле" через SIGNAL/SLOT макросы.

Вообще этот Consumer выглядит подозрительным/избыточным. Что он должен делать? Связвывать/развязывать? Так это само по себе не основание заводить класс


Название: Re: Множественное наследования от QObject или подключения к сигналам не в QObject-а
Отправлено: MaxoBik от Июль 23, 2015, 16:59
Цитировать
'QObject::connect' : none of the 4 overloads could convert all the argument types


т.е.:
Код:
QObject * dst = dynamic_cast <QObject *> (this);
QObject::connect( semitter, &SignalEmiter::someSignal1, dst, &SignalEmiterConsumer::someSlot1 );
При таком раскладе SignalEmiterConsumer не может иметь слотов - он ведь не QObject. Ну это и не нужно (хотя это часто хотят иметь :)). Но можно связывать "в старом стиле" через SIGNAL/SLOT макросы.

Вообще этот Consumer выглядит подозрительным/избыточным. Что он должен делать? Связвывать/развязывать? Так это само по себе не основание заводить класс
Ну как минимум он предоставляет строгую формализацию объекта, показывая ошибки когда мы что-то забыли.
Да подключения-отключения событий кажется тривиальной задачей, но когда у вас скажем 10 разных таких подписчиков, иногда динамически подгружаемых-отгружаемых, каждый раз копипастить один и тот же код - утомляет и вполне может порождать ошибки при копипасте.
Да, "в старом стиле" все подключается, спасибо.