2010-12-09 1 views
28

Возможно ли иметь класс шаблона, который наследует от QObject (и имеет макрос Q_OBJECT в его объявлении)?QT: Templated Q_OBJECT класс

Я хотел бы создать что-то вроде адаптера для слотов, что бы что-то сделать, но слот может принимать произвольное количество аргументов (количество аргументов зависит от аргумента шаблона).

Я просто попытался сделать это и получил ошибки компоновщика. Я думаю, gmake или moc не получают вызов этого класса шаблона. Есть ли способ сделать это? Может быть, явно создавая шаблоны?

+0

Вы наблюдали модель включения? :) http://linuxtopia.org/online_books/programming_books/c++_practical_programming/c++_practical_programming_134.html – 2010-12-09 11:04:42

+0

@Armen Да, я об этом не думал. Я думал, что препроцессор qt захочет его записать. – 2010-12-09 11:07:54

ответ

1

Я попытался явно инстанцировании шаблоны, и получил это:

core_qta_qt_publisheradapter.hpp: 96: Ошибка: классы шаблонов не поддерживаются Q_OBJECT

Я думаю, что ответ на мой вопрос.

EDIT

На самом деле, если поместить все определение класса шаблона в заголовке, то кварты препроцессор не обрабатывает его, а затем я получаю ошибки компоновщика. Поэтому это должно быть возможно, если я добавлю недостающие методы.

EDIT # 2

This library сделал именно то, что я хотел - использовать механизм пользовательского сигнала/слот, где слот не определенную подпись.

9

Принимая во внимание некоторые ограничения: вы можете. Сначала, пожалуйста, ознакомьтесь (если уже нет) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html. - это поможет его имитировать. А насчет ограничений: вы можете иметь шаблон QObject класс т.е. шаблонный класс, производный от QObject, но:

  1. Не говори МОЦ скомпилировать его.
  2. Q_OBJECT просто макро, и вы должны заменить его на него реальный контент, который является виртуальным интерфейсом и что-то еще :)
  3. Осуществить активацию QMetaObject (выше упомянутого виртуального интерфейса и быть осторожность при работе с объектом данных, информация Снято что является также исходить от Q_OBJECT) и некоторых функциональных возможностей еще и вы будете иметь шаблон QObject (даже с пазами шаблонных)
  4. Но, как мне удалось поймать один отдернуть - это не возможно просто использовать этот класс, как база для другого класса.
  5. Есть и другие недостатки - но я думаю, что деталь расследование покажет вам их.

Надеюсь, это поможет.

23

Это не возможно смешивать шаблон и Q_OBJECT, но если у вас есть подмножество типов вы можете перечислить слоты и сигналы, как это:

class SignalsSlots : public QObject 
    { 
     Q_OBJECT 

    public: 
     explicit SignalsSlots(QObject *parent = 0) : 
      QObject(parent) {} 

    public slots: 
     virtual void writeAsync(int value) {} 
     virtual void writeAsync(float value) {} 
     virtual void writeAsync(double value) {} 
     virtual void writeAsync(bool state) {} 
     virtual void writeAsync(svga::SSlideSwitch::SwitchState state) {} 

    signals: 
     void readAsynkPolledChanged(int value); 
     void readAsynkPolledChanged(float value); 
     void readAsynkPolledChanged(double value); 
     void readAsynkPolledChanged(bool state); 
     void readAsynkPolledChanged(svga::SSlideSwitch::SwitchState state); 
    }; 
... 
template <class T> 
class Abstraction : public SignalsSlots 
{... 
1

Это еще нельзя смешивать шаблоны и Q_OBJECT, но в зависимости в вашем случае использования вы можете использовать новый синтаксис «connect». Это позволяет, по крайней мере, использовать шаблоны-слоты.

Классическая нерабочим подход:

class MySignalClass : public QObject { 
    Q_OBJECT 
public: 

signals: 
    void signal_valueChanged(int newValue); 
};  


template<class T> 
class MySlotClass : public QObject { 
    Q_OBJECT 
public slots: 
    void slot_setValue(const T& newValue){ /* Do sth. */} 
}; 

Желаемая использование, но не компилируется:

MySignalClass a; 
MySlotClass<int> b; 

QObject::connect(&a, SIGNAL(signal_valueChanged(int)), 
       &b, SLOT(slot_setValue(int))); 

Error: Template classes not supported by Q_OBJECT (For MySlotClass).

Решение с использованием нового в «connect'-синтаксис:

// Nothing changed here 
class MySignalClass : public QObject { 
    Q_OBJECT 
public: 

signals: 
    void signal_valueChanged(int newValue); 
}; 


// Removed Q_OBJECT and slots-keyword 
template<class T> 
class MySlotClass : public QObject { // Inheritance is still required 
public: 
    void slot_setValue(const T& newValue){ /* Do sth. */} 
}; 

Теперь мы можем создать нужные объекты MySlotClass и подключить их к соответствующим источникам сигнала.

MySignalClass a; 
    MySlotClass<int> b; 

    connect(&a, &MySignalClass::signal_valueChanged, 
      &b, &MySlotClass<int>::slot_setValue); 

Вывод: Использование шаблонов слотов возможно. Испускание шаблонных сигналов не работает, поскольку ошибка компилятора возникает из-за отсутствия Q_OBJECT.