web-dev-qa-db-fra.com

QT: classe Q_OBJECT modèle

Est-il possible d'avoir une classe de modèle, qui hérite de QObject (et a la macro Q_OBJECT dans sa déclaration)?

Je voudrais créer quelque chose comme un adaptateur pour les emplacements, ce qui ferait quelque chose, mais l'emplacement peut prendre un nombre arbitraire d'arguments (le nombre d'arguments dépend de l'argument du modèle).

J'ai juste essayé de le faire et j'ai eu des erreurs de l'éditeur de liens. Je suppose que gmake ou moc ne sont pas appelés sur cette classe de modèle. Y a-t-il un moyen de faire cela? Peut-être en instanciant explicitement les modèles?

43
BЈовић

Il n'est pas possible de mélanger le modèle 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
{...
35
Jonas W

Tenant compte de certaines restrictions: vous le pouvez. Veuillez d'abord vous familiariser (si ce n'est déjà fait) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html . - cela aidera à l'implémenter. Et à propos des restrictions: vous pouvez avoir un modèle de classe QObject, c'est-à-dire une classe de modèle dérivée de QObject, mais:

  1. Ne dites pas au moc de le compiler.
  2. Q_OBJECT est juste une macro et vous devez le remplacer par du vrai contenu qui est une interface virtuelle et autre chose :)
  3. Implémentez l'activation QMetaObject (interface virtuelle mentionnée ci-dessus et soyez prudent avec les données d'informations sur l'objet, qui proviennent également de Q_OBJECT) et d'autres fonctionnalités et vous aurez le modèle QObject (même avec les emplacements de modèle)
  4. Mais comme j'ai réussi à rattraper le seul tirage en arrière - il n'est pas possible simplement d'utiliser cette classe comme base pour une autre classe.
  5. Il y a d'autres inconvénients - mais je pense que l'enquête détaillée vous les montrera.

J'espère que cela vous sera utile.

12
milyaaf

Il n'est toujours pas possible de mélanger les modèles et Q_OBJECT mais selon votre cas d'utilisation, vous pouvez utiliser la nouvelle syntaxe 'connect'. Cela permet au moins l'utilisation de modèles d'emplacements.

approche classique non fonctionnelle:

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. */}
};

Utilisation souhaitée mais non compilable:

MySignalClass a;
MySlotClass<int> b;

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

Erreur: classes de modèle non prises en charge par Q_OBJECT (pour MySlotClass).

Solution utilisant la nouvelle syntaxe '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. */}
};

Nous pouvons maintenant instancier les objets "MySlotClass" souhaités et les connecter aux émetteurs de signaux appropriés.

  MySignalClass a;
  MySlotClass<int> b;

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

Conclusion: L'utilisation des emplacements de modèle est possible. L'émission de signaux de modèle ne fonctionne pas car une erreur de compilation se produira en raison de Q_OBJECT manquant.

3
Anonymous

J'ai essayé d'instancier explicitement des modèles et j'ai obtenu ceci:

core_qta_qt_publisheradapter.hpp: 96: Erreur: classes de modèle non prises en charge par Q_OBJECT

Je suppose que cela répond à ma question.

[~ # ~] modifier [~ # ~]

En fait, si je place toute la définition de classe de modèle dans l'en-tête, le préprocesseur qt ne le traite pas, puis j'obtiens des erreurs de l'éditeur de liens. Il doit donc être possible de le faire si j'ajoute des méthodes manquantes.

EDIT # 2

Cette bibliothèque a fait exactement ce que je voulais - utiliser un mécanisme de signal/slot personnalisé, où le slot n'a pas de signature définie.

1
BЈовић