QT: Templated Q OBJECT class
est-il possible d'avoir une classe template, qui hérite de QObject (et a la macro Q_OBJECT dans sa déclaration)?
je voudrais créer quelque chose comme l'adaptateur pour les fentes, qui ferait quelque chose, mais la fente peut prendre le nombre arbitraire d'arguments (le nombre d'arguments dépend de l'argument de modèle).
j'ai juste essayé de le faire, et j'ai eu des erreurs de linker. Je suppose que gmake ou moc ne vont pas être appelés sur ce cours de template. Est-il un moyen de faire cela? Peut-être par instancier explicitement modèles?
4 réponses
il n'est pas possible de mélanger template et Q_OBJECT mais si vous avez un sous-ensemble de types, vous pouvez lister les slots et les signaux comme ceci:
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
{...
en tenant compte de certaines restrictions: vous pouvez. D'abord veuillez devenu familier (si pas déjà) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html. - il vous aidera à imlement. Et à propos des restrictions: vous pouvez avoir une classe template QObject, c'est-à-dire une classe template dérivée de QObject, mais:
- ne dites pas au moc de compiler.
- Q_OBJECT est juste une macro et vous devez la remplacer par It real contenu qui est l'interface virtuelle et autre chose :)
- implémenter l'activation de QMetaObject (interface virtuelle mentionnée ci-dessus) et soyez prudent avec les données d'information d'objet, qui est également venu de Q_OBJECT) et d'autres fonctionnalités et vous aurez template QObject (même avec les fentes de template)
- mais comme j'ai réussi à attraper le seul retrait - il n'est pas possible de tout simplement utilisez cette classe comme base pour une autre classe.
- Il y a d'autres inconvénients, mais je pense que le détail l'enquête permettra de vous les montrer.
Espérons que ce sera utile.
j'ai essayé explicitement d'instancier des modèles, et j'ai obtenu ceci:
core_qta_qt_publisheradapter.php:96: Erreur: Modèle de classes non pris en charge par la macro q_object
je suppose que cela répond à ma question.
EDIT
en fait, si je place toute la définition de la classe template dans l'en-tête, alors le préprocesseur qt ne la traite pas, et j'obtiens des erreurs de linker. Il doit donc être possible de le faire, si j'ajoute manquant méthode.
EDIT #2
Cette bibliothèque fait exactement ce que je voulais, d'utiliser un signal/slot mécanisme, où le logement n'a pas défini par la signature.
il n'est toujours pas possible de mélanger les templates et Q_OBJECT, mais selon votre cas d'utilisation, vous pouvez utiliser la nouvelle syntaxe 'connect'. Cela permet au moins l'utilisation de gabarits-slots.
approche classique de non-travail:
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. */}
};
usage souhaité mais non compilable:
MySignalClass a;
MySlotClass<int> b;
QObject::connect(&a, SIGNAL(signal_valueChanged(int)),
&b, SLOT(slot_setValue(int)));
Erreur: Modèle de classes non pris en charge par la macro q_object (Pour MySlotClass).
Solution en utilisant le nouveau "se connecter" -syntaxe:
// 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. */}
};
maintenant nous pouvons instancier les objets 'MySlotClass'désirés et les connecter aux émetteurs de signal appropriés.
MySignalClass a;
MySlotClass<int> b;
connect(&a, &MySignalClass::signal_valueChanged,
&b, &MySlotClass<int>::slot_setValue);
Conclusion: utilisation de gabarits-les fentes sont possibles. Emitting template signals ne fonctionne pas car une erreur de compilateur se produira à cause de Q_OBJECT manquant.