2016-03-08 1 views
0

J'ai trouvé, en répondant à une autre de mes propres questions (here), que QObject::findChildren<T> retournera tout enfant qui passe reinterpret_cast<T>.Comment remplacer QObject :: findChildren pour renvoyer uniquement le type dérivé

Je voudrais remplacer le comportement afin que je ne reçoive que des types dérivés. C'est parce que j'ai un modèle composite, où tous les éléments sont du même type de base, mais je voudrais utiliser findChildren pour trouver des sous-classes spécifiques.

J'ai essayé prépondérants findChildren comme suit:

template <class T> 
QList<T> Section::findChildren(QString name) 
{ 
    QList<T> siblings = QObject::findChildren<T>(name); 
    QList<T> children; 
    for(int i=0; i < siblings.size(); i++) 
    {  
    T test = siblings.at(i); 
    T child = dynamic_cast<T>(test); 
    if(child) 
     children << child; 
    } 
    return children; 
} 

Dans mon exemple, je l'ai dis quatre articles que pour enfants, et deux sont d'un type, deux d'une autre, avec la même classe de base. Je passe un des types dérivés pour T et comme attendu (maintenant) QObject :: findChildren donne les quatre enfants. Mais je m'attends à ce que dynamic_cast ne réussisse que deux fois, il le fait quatre fois. Si je transmets la liste renvoyée de quatre éléments en dehors de la fonction de modèle, je peux la sélectionner avec succès pour les deux éléments que je recherche.

+0

Depuis 'QObject :: findChildren()' est pas virtuel, vous ne pouvez pas l'ignorer. Ce que vous faites est simplement * l'occulter *. Votre méthode ne sera appelée que si vous l'appelez directement sur un objet, une référence ou un pointeur 'Section'. –

+0

Très bien - je frappe le code, je sais que je vais l'appeler seulement sur une section. Cela ne me dérange pas d'avoir un nom légèrement différent - mais le comportement est inattendu pour moi. – mike

+1

"n'importe quel enfant qui passe reinterpret_cast" - à peu près tous les pointeurs peuvent être lancés sur n'importe quel autre pointeur avec ce marteau contondant. Se sent comme quelque chose ne va pas dans vos hypothèses ou le code que vous n'avez pas montré. Pourriez-vous fournir un [mcve]? – Mat

Répondre

1

EDIT: L'OP a compris qu'il utilisait Q_OBJECT macro incorrectement dans sa hiérarchie de classes. Je laisse la réponse originale, il a accepté ci-dessous, mais la bonne réponse est que l'on doit utiliser macro Q_OBJECT dans la base ainsi que des classes dérivées.

RÉPONSE ORIGINAL: Si QObject::findObject() utilise vraiment reinterpret_cast<>, tous les moulages à T réussira même si le type ne peut pas être représenté. Cela n'a aucun sens sur la base de la description de l'API. En supposant que vous avez raison sur ce point, cependant, votre implémentation est erronée car vous obtenez une liste de frères et soeurs qui sont déjà T en raison de la reinterpret_cast<>. Au lieu de cela, vous devez utiliser QObject puis utiliser dynamic_cast<> pour éliminer les instances que vous voulez comme ceci:

template <class T> 
QList<T> Section::findChildren(QString name) 
{ 
    QList<QObject*> siblings = QObject::findChildren<QObject*>(name); 
    QList<T> children; 
    for(int i=0; i < siblings.size(); i++) 
    {  
    QObject* test = siblings.at(i); 
    T child = dynamic_cast<T>(test); 
    if(child) 
     children << child; 
    } 
    return children; 
} 
+0

Merci - cela fonctionne magnifiquement. – mike

+1

Bien que cela n'aurait pas dû être nécessaire - si j'avais utilisé Q_OBJECT dans toutes les définitions de sous-classes, j'aurais vu ce que j'attendais. – mike