8
votes

Moyen le plus élégant de contourner ce problème de polymorphisme

Edit: Je travaille avec C ++.

Donc, je crée des méthodes / fonctions pour tester l'intersection entre les formes. J'ai essentiellement cela: xxx

Maintenant, je dois décider de la meilleure façon d'écrire les méthodes / fonctions réelles pour tester l'intersection. Mais toutes mes formes seront stockées dans une liste de pointeurs de forme. Je vais donc appeler une méthode / fonction du formulaire de base: xxx

à ce point, j'ai besoin de Déterminez quels types de formes 'A' et 'B' sont, donc je peux détecter correctement les collisions. Je peux facilement faire l'un d'entre eux, en utilisant simplement certaines méthodes virtuelles: xxx

qui déterminerait l'une des formes ("A" est maintenant "ceci"). Cependant, j'aurais toujours besoin d'obtenir le type de 'B'. La solution évidente consiste à donner une variable «ID» à classer quelle forme elle est, puis «commutateur» à travers celles-ci, puis utilisez dynamic_cast. Cependant, ce n'est pas très élégant, et on a l'impression qu'il devrait y avoir une autre façon de le faire.

Toute suggestion?


2 commentaires

C'est le problème classique qui est résolu par double envoi.


Bien que mes recherches originales ne soient jamais présentées avec une double envoi, je vois comment cela résout mon problème. Merci. Edit: Je voterais, mais je ne suis pas sûr de ne pas avoir assez de réputation, ou je ne peux tout simplement pas trouver le bouton UP-VOTE.


5 Réponses :


4
votes

andrei alexandrescu détail de ce problème dans son classique moderne C ++ Design . La bibliothèque de compagnie Loki contient le La mise en œuvre des multi-méthodes .

mise à jour

LOCI fournit trois implémentations de multi-méthodes, en fonction des besoins de l'utilisateur. Certains sont pour la simplicité, certains sont à la vitesse, certains sont bons pour un faible accouplement et certains offrent plus de sécurité que d'autres. Le chapitre du livre s'étend sur près de 40 pages et il suppose que le lecteur se familiarise avec plusieurs concepts du livre - si vous êtes à l'aise avec Boost, puis Loki peut être dans votre allée. Je ne peux vraiment pas distiller que pour une réponse acceptable pour le cas, mais je vous ai signalé la meilleure explication du sujet de C ++ que je connaisse.


3 commentaires

@anon_downvoter sauf si vous justifiez votre action, cela n'aide pas beaucoup.


Manque de code peut-être? Quoi qu'il en soit, oui, les multi-méthodes seraient utiles.


@Matthieuum. Peut-être. J'ai développé ma réponse pour expliquer pourquoi je n'ai pas fourni d'exemple. Merci.



1
votes

Vous pouvez ajouter un champ saleType à chaque forme

par exemple: xxx


0 commentaires

7
votes

5 commentaires

Le constructeur que vous avez défini pour l'intersection n'a aucun argument et que vous l'appelez plus tard avec des arguments. Pourquoi?


@ user1754322: Je n'ai pas pu repérer l'appel, en effet, il me semble que je ne l'appelle pas du tout. Étiez-vous confondu par Boost :: SCOPED_PTR INTERSECTEUR (gauche.Interecther ()); où je crée une variable Variable nommée intersecteur ?


Je pensais boost :: scoped_ptr intersecteur (gauche.Interacteur ()); était quelque chose comme intersecteur intersecteur (gauche.Interectrice ()); n'est-ce pas?


@ user1754322: non, boost :: scoped_ptr est construit à partir d'un interservateur , comme on peut déduire de la signature de l'interservateur méthode dans les différentes classes.


Merci, je pensais que Scoped_ptr en fait un autre maintenant je comprends.



2
votes

Le polymorphisme d'exécution de C ++ a une seule envoi (la classe de la classe de base).

Il y a diverses solutions à votre problème, mais aucun d'entre eux n'est "élégant", car ils essaient tous de forcer la langue à faire plus que cela peut soutenir de manière native (Alexandrescu Loki MultiMethods est un ensemble très bon caché de hacks: il encapsule les "mauvaises choses", mais ne font pas le bien)

Le concept, ici, il faut écrire toutes les fonctions N 2 des combinaisons possibles et trouvez un moyen de les appeler en fonction du type d'exécution de deux paramètres. Le "modèle de visiteur" (rappelez une onction virtuelle à partir d'une autre fonction virtuelle), la technique "mutiléthod" (utilise une table DSPatch générique), "Dynamic Cast" dans une fonction virtuelle ou "Dual dynamic_cast" sur toutes les fonctions Tous font la même chose: appelez une fonction après deux indirectes. Aucun d'entre eux ne peut être défini techniquement "mieux que l'autre" car la performance résultante est la plupart des mêmes.

Mais certains d'entre eux coûtent plus cher que l'autre dans la rédaction de code et d'autres coûts supplémentaires dans la maintenance du code. Vous avez le plus de chances d'essayer d'estimer dans votre cas ce que le compromis est. Combien de classes autres vous pensez peut avoir besoin d'ajouter à l'avenir?


0 commentaires

0
votes

J'ai joué avec l'intersection des formes résolvant l'approche d'expédition juste pour le plaisir. Je n'ai pas aimé l'idée d'étendre les cours à chaque nouvelle forme de nouvelle forme. J'ai pensé à la collecte de résolveurs d'intersection qui est itéité de savoir s'il y en a un qui prend en charge une paire de formes donnée. Si une nouvelle forme apparaît de nouvelles résolveurs d'intersection doit être ajoutée à la collection.

Je ne pense pas qu'il s'agisse d'une approche la plus optimale en termes de performance, car les résolveurs itéRés à travers et les moulages dynamiques exécutés jusqu'à ce que le résolveur approprié soit trouvé. p>

mais, néanmoins ... p>

Le résolveur d'intersection prend deux formes et le résultat de résolution de retour qui contiennent des drapeaux supportés et intersect. P>

rectangle drawn
triangle drawn
circle drawn
rectangles intersect
9Rectangle - 8Triangle intersection resolving not supported
rectangle intersect circle
8Triangle - 9Rectangle intersection resolving not supported
8Triangle - 8Triangle intersection resolving not supported
8Triangle - 6Circle intersection resolving not supported
rectangle intersect circle
6Circle - 8Triangle intersection resolving not supported
6Circle - 6Circle intersection resolving not supported


0 commentaires