2016-02-25 2 views
1

que je veux transmettre mes objets en fonction de leur classe de base:
connect(pCaller, SIGNAL(sig2(const IBase &)), pReceiver, SLOT(slot2(const IBase &)));

Mais je reçois exécution erreur:Le passage de paramètres de classe abstraite par des références à des signaux et slots

QObject::connect: Cannot queue arguments of type 'IBase' (Make sure 'IBase' is registered using qRegisterMetaType().)

pourquoi j'ajouter:
qRegisterMetaType<IBase>("IBase");

Et obtenir un compilation erreur:

error C2259: 'IBase': cannot instantiate abstract class

Quelle est la meilleure façon de résoudre ce problème?

+1

Je pense que vous recherchez ceci: http://stackoverflow.com/questions/17943496/declare-abstract-signal- in-interface-class/17943699 –

+1

Il semble que ce soit impossible.D'après ce que je comprends, Qt nécessite un constructeur de copie pour les paramètres donnés par la référence const: http://stackoverflow.com/a/8457129/4149835 –

+0

@VladimirBershov après avoir lu le réponse du lien que vous avez fourni J'ai ajouté l'argument 'Qt :: DirectConnection' à mon appel' connect' et cela semble fonctionner :) Mais je ne suis pas sûr que ce soit un "hack" ou en fait le bon chemin :) Merci –

Répondre

3
  1. Votre classe IBase doit être copiable et constructible, si vous voulez passer directement (pas pointeur throught)
  2. Vous devez vous enregistrer IBase * avec Q_DECLARE_METATYPE macro dans votre tête (uniquement dans l'espace global) - Q_DECLARE_METATYPE(IBase *). Les pointeurs sont de type POD, donc ils sont copiables/constructibles.
  3. Si vous voulez passer IBase * entre différents threads, vous devez enregistrer la classe avec qRegisterMetaType<IBase *>() appel;
  4. Il est de mauvaise pratique de passer des pointeurs à travers des singals, car il est difficile de contrôler la durée de vie des objets passés.
  5. Bonne solution de contournement: vous pouvez enregistrer votre type avec la macro Q_DECLARE_METATYPE(IBase *) et envelopper votre variable avec QVariant: QVariant wrapper; wrapper.setValue(p); p = wrapper.value<IBase *>();.
+0

1. Je vais le passer comme référence (afaik le même que le pointeur) 5. Semble fishy comme' reinterpret_cast' sledgehammer, merci t ho. Je vais essayer d'appliquer vos suggestions un peu plus tard –

+0

Alexey, vous ne pouvez pas décider, comment le passer. C'est par conception de Qt - si vous passez un certain type de données, il doit être constructible + copiable. –

+0

merci, ça va faire. Question rapide, pourquoi utilisez-vous qRegisterMetaType () 'quand qt docs ils écrivent' qRegisterMetaType ("IBase") '? –

0

Vous obtenez cette erreur parce que l'appelant et le récepteur vivent dans différents threads. Les invocations d'emplacement de thread croisé doivent pouvoir copier tous les arguments. Puisque vous passez un type de base par référence, il n'y a généralement aucun moyen de le copier :(

+0

J'ai ajouté l'argument 'Qt :: DirectConnection' à mon appel' connect' et maintenant il ne fait aucune copie. Qu'est ce que tu penses de ça? –

+0

Les valeurs réelles sont des types dérivés de 'IBase'. Désolé je ne l'ai pas mentionné, je pensais que c'était évident :) –

+0

@AlexeyAndronov "J'ai ajouté l'argument Qt :: DirectConnection à mon appel de connexion et maintenant il ne fait aucune copie. L'emplacement est-il sûr pour les threads? Si c'est le cas, ça va bien sûr fonctionner. "Les valeurs réelles sont de types dérivés de IBase" So? Oui, c'est évident, et ma réponse en tient compte, bien sûr :) Vous pouvez rendre 'IBase' copiable en utilisant l'idiome du constructeur virtuel. –