10
votes

En C ++, vérifiez si deux instances d'une classe de base sont en infraction de la même sous-classe

Le code ci-dessous explique le problème. Remplir le même_sub_class pour détecter si Les deux pointeurs à la classe de base virtuelle A sont en fait le même concret classe.

struct A {
    ...
}:

struct B : public A {
    ...
}:

struct C : public A {
    ...
}


bool same_sub_class(A * a1, A * a2){
    // Fill this in to return true if a1 and a2 are
    // of the same concrete class
}


1 commentaires

On dirait que ce dont vous avez vraiment besoin est une INT statique sur chaque classe à trier par?


6 Réponses :


21
votes

Si vous pouvez utiliser RTTI,

#include <typeinfo>


8 commentaires

Vous devez vous rappeler d'inclure aussi.


Mais A doit être polymorphe n'est pas ??


@Liak, oui, la classe de base doit avoir au moins une fonction virtuelle.


@Tim merci pour ça. J'ai fait une édition sur la question pour mieux refléter le problème que j'essaie de résoudre. S'avère que la simple égalité n'est pas tout à fait ce dont j'ai besoin.


@Bradgonesurfing Découvrez ma mise à jour. Je ne suis pas sûr si je l'obtiens.


"Hash la chaîne renvoyée de typeid (* PTR) .name ()" - Ouch! Voyons: OP doit avoir au moins une fonction virtuelle quand même, pour typeid pour fonctionner. L'ajout d'une fonction virtuelle ne renvoie pas type_id comme simple int le moyen le plus simple?


@Maciej Hehl, je pense que ce serait le meilleur. J'essayais juste de mettre à jour ma réponse sans le changer complètement. C'est vraiment une question complètement différente.


Fabriquez un membre «Typetag» protégé initialisé dans le constructeur de sous-classes, comme je l'ai suggéré ci-dessous. Ensuite, vous pouvez avoir Hash ou regroupez vos instances sur ce membre.



9
votes
typeid(*a1) == typeid(*a2)
Note the dereference, it is important.

0 commentaires

2
votes

Vous pouvez créer votre propre identifiant de type: xxx

puis dans les constructeurs de sous-classes: xxx


7 commentaires

TypeTag mieux être privé. Pas énumé mais variable.


@Manoj: Je suis en désaccord. Typetag est initialisé dans le constructeur de Soublasses, il ne peut donc pas être membre privé de la classe de base.


@Adadesit: TypeTag doit être protégé. Mais ce mécanisme n'est pas parfait, car sur l'ajout de nouveau descendant, nous devons ajouter de nouveaux membres de l'énum. Cordialement à Odessa :)


Je pense que c'est une mauvaise idée, mieux d'utiliser RTTI


@Piotr il n'est pas juste de simplement dire «ce mauvais» à moins que vous ne fournissez une raison. Je ne le sais pas à coup sûr, mais je pense que mon idée est une sorte de ce que RTTI est à l'intérieur. De manière générale, la plupart du temps, c'est bon à coller à la norme, mais il est parfois préférable de mettre en œuvre quelque chose vous-même. Nous ne connaissons pas les circonstances exactes de l'affiche. Considérez par exemple que RTTI n'est pas pris en charge sous Android NDK.


groups.google.com/group/android-ndk/ Browse_thread / thread / ...


Link intéressant: Quelqu'un a construit une version personnalisée de NDK qui prend en réalité le support RTTI. C'est très bien. Mais note, ce n'est pas le NDK de Google d'origine.



1
votes

Il existe une fonctionnalité dans C ++ appelée RTTI (informations de type d'exécution) qui vous permet de faire de telles choses.

Une autre possibilité d'avoir une vérification de type d'exécution consiste à créer une classe de base à partir de laquelle toutes vos classes dérivent de. Dans votre classe de base, citons un champ contenant son type comme une chaîne ou un numéro.


0 commentaires

0
votes

Un astuce qui peut ne pas fonctionner avec RTTI, selon votre compilateur, est la suivante

const type_info &a1_type_info= typeid(*a1);
const type_info &a2_type_info= typeid(*a2);

return &a1_type_info==&a2_type_info || a1_type_info==a2_type_info;


0 commentaires

2
votes

En réalité, il y a une réponse assez simple à cela. Mais cela implique de poser les questions un peu plus claires.

(a) Si je veux stocker des objets TypeInfo dans un ONUORDED_SET, que dois-je faire?

TypeInfo prend en charge le == et la méthode Nom (). Le nom peut être utilisé pour générer un hachage et == pour l'égalité

(b) Si je veux stocker des objets TypeInfo dans une commande commandée (STD :: Set), que dois-je faire?

typeInfo prend en charge le == et la méthode avant (). Avec un peu d'emballage de ces deux méthodes, je peux implémenter une interface pour une fonction de comparaison qui me donne une forte commande stricte.


0 commentaires