
Envoyé par
XAMLdev
ET l’esprit d’aventure alors ?
Oh, je ne t'empêche pas du tout d'essayer de porter du C# en C++, bien au contraire 
EN fait mon code C# a déjà été pensé en terme de portage du coup il est optimisé pour être transcrit.
Oui, mais visiblement tu essayes de le transcrire pour ainsi dire mot à mot, et c'est là qu'est le problème 
Je ne dis pas que ce sera du 1 pour 1 mais ça ne devrait pas en être loin.
Tu pourras, très certainement, garder l'organisation et les hiérarchies de classes, cela, je n'en doute pas une seule seconde. Mais
Il n'est pas impossible que tu doive rajouter une ou deux classe pour servir de "pont".
Certaines techniques qui peuvent te sembler naturelles en C# (comme le fait d'utiliser des pointeurs de fonctions
) ne le sont vraiment pas, ou du moins, ne sont vraiment pas recommandées en C++
C’est simple. Dans mon archi, un message est un type asexué.
En C#, cela se peut, mais pas en C++
C'est-à-dire que je ne transmets dans le constructeur d’un message que des paramètres de type simples ou généraux. Les capacités de tirs ne spécialisent pas les messages.
Je n'ai pas dit que les capacités de tir spécialisent les messages, j'ai dit
- Quel que soit le message effectivement envoyé, il peut être considéré comme un message d'ordre général (il existe une hiérarchie de classe dont la classe de base est un message "sans précision")
- Que chaque capacité de tir est susceptible d'émettre un message spécifique dont le type réel dépend, tout bien considéré, de la capacité de tir elle-même
- que nous pourrions donc profiter intelligemment du polymorphisme lorsqu'il s'agit de faire la transition entre le message et le projectile
De plus comme les capacités de tors génèrent et gèrent leur message, elles ne peuvent pas transmettre leur type (sous forme d’instance par exemple). Ceci conduirait à une belle référence circulaire.
Quand bien même, les référence circulaires au sein d'un module sont courantes en C++ 
Par contre, dans le cas présent, la référence circulaire est surtout le symptome de ce que j'expliquais plus haut: La capacité de tir peut etre à l'origine de ce qui provoque la création d'un projectile, mais n'a strictement rien à voir avec la destruction de celui-ci.
Et encore: à bien y réfléchir, ce n'est pas la capacité de tir elle même qui provoque la création du projectile, mais un événement particulier (clique sur la souris, appuis sur la barre d'espace, ...) qui devrait utiliser la capacité de tir afin de déterminer quel type de projectile sera créé.
De plus mes capacités de tirs sont libres d’être ce qu’elles veulent : une classe seule, une classe dérivée, une classe composée.
Mais elles auront sans doute (ou devraient avoir) toutes un point commun: le fait de dériver d'une classe de base identique, non
Il y a sans doute moyen de faire sans (en utilisant le paradigme générique), mais ca risque de faire vraiment compliqué
Peu importe son type ça ne doit pas influer sur la structure du message qui ne passe que des infos primaires.
Ca, j'en suis beaucoup moins sur...
Oui, le message ne transmet très certainement que des informations primaires, mais non je ne crois pas que tu puisses estimer que le type de ta capacité de tir n'influe pas sur le type du message en lui-même.
Le fait est que les informations transmises par le message peuvent être d'ordre tout à fait différent en fonction du projectile à envoyer.
Je ne parle pas ici de "simplement" envoyer des valeurs différentes pour des données qui seront transmises de manière systématique, je parle de transmettre, pour certains types de projectiles, des données supplémentaires spécifique, bien sur 
Du coup pour faire un genre de callbak, je passe le pointeur de fonction qui comme je l’ai dit en C# est un type définit qui ne change pas suivant sa localisation. Là encore ça n’oblige pas le message à être spécialement typé.
Sauf que, pour pouvoir utiliser une fonction membre comme callback, tu as besoin... de l'objet au départ duquel elle est appelée, à moins d'en faire une fonction statique.
Et même dans ce cas, une fonction membre statique devra alors connaitre... l'instance particulière de ton instance de tir qui doit prendre en charge la destruction de ton projectile.
J'attires, en outre, ton attention sur un fait assez particulier en ce qui concerne les pointeurs sur fonctions membres:
La signature d'une fonction membre est pleinement qualifiée, c'est à dire que le nom de la fonction membre contient le type d'objet auquel elle appartient.
Lorsque tu écris un code proche de
typedef void (B::*ParameterlessFunctionPointer)(void);
tu défini ParameterlessFunctionPointer comme un pointeur sur une fonction issue du type B ne prenant aucun argument et ne renvoyant rien. MAIS
si C hérite de B et que la fonction que tu veux utiliser n'existe que dans C, la fonction n'entre pas dans cette définition parce que ce n'est plus une fonction de B, mais bien une fonction (spécifique!!) de C.
Le typedef pour le pointeur de fonction d'une fonction membre qui n'apparait pas dans B est proche de
typedef void (C::*ParameterlessFunctionPointer)(void);
et est incompatible avec le typedef précédent.
Cependant, il existe une alternative aux pointeurs de fonction: les foncteurs (ou, si tu préfères, les "objets fonctions").
Ce sont des classes ou des structures qui exposent essentiellement un opérateur ( l'opérateur () pour ce qui nous intéresse ici) et qui peut parfaitement être dérivé en différentes "saveurs" 
Oui par exemple des projectiles composés comme des explosions par fragmentation. Et bien d’autres choses …
Oui, je ne sais pas pourquoi cela me surprenais, mais bon..
Non, je ne transmets pas de type dans mes messages de tirs.
En y réfléchissant bien, tu as raison de le faire ainsi: le projectile est totalement indépendant tant du tireur que de la capacité de tir qui l'a généré: il vit sa vie et n'a plus de compte à rendre ni à l'un ni à l'autre
.
La capacité de tir est un médiateur entre les projectiles qu’elle génère et le tireur qui tire.
Je l'avais bien compris sous cette forme.
Mais la responsabilité du tireur et de la compétence de tir vis à vis du projectile tiré s'arrête... au moment où le projectile est tiré.
Une fois qu'il est tiré, le projectile n'a plus rien à voir ni avec l'un ni avec l'autre 
Il y en a certains cas ou la façon de tirer fait que le projectile impose un comportement à la capacité de tir qui maintient un état particulier du tireur : ce n’est pas fréquent mais ça arrive.
Oui, mais, dans ce cas, le changement d'état de la capacité de tir ne devrait pas être directement induit par le projectile: tu devrais avoir un contrôleur qui modifie l'état de la capacité de tir en fonction de l'état du projectile tiré 
Le code de la capacité de tir que tu as donné est pratiquement le mien sauf que les opérations que je fais en call back ne sont pas de destruction du projectile ( ta méthode detruisMoi(Projectile * ) = 0).
C'était un exemple simple pour te faire comprendre 
Ce qui était important à comprendre, c'est que, si tu veux que le projectile puisse communiquer directement d'une manière ou d'une autre avec la capacité de tir, ce qu'il te faut c'est:
- soit une hiérarchie de classes spécifique (prenant la forme d'un foncteur) qui permet d'invoquer des fonctions spécifiques pour chaque capacité de tir
- soit un comportement polymorphe au niveau de la classe de base des capacités de tir qui sera appelé de manière systématique par le projectile, quitte à ce que ce comportement polymorphe ne fasse strictement rien
Dans les deux cas, il faut bien que le projectile ou que le foncteurs dispose... de l'instance particulière de la capacité de tir vers laquelle se tourner pour invoquer les fonctions en questions 
Et comme nous sommes finalement dans une situation dans laquelle différentes données "métier" sont susceptibles d'entrer en jeu d'une part et dans laquelle il ne rentre pas dans la responsabilité du projectile d'avoir la moindre relation vis à vis de la capacité de tir qui a provoqué sa création d'autre part, nous sommes bel et bien dans une situation dans laquelle toute cette gestion devrait être "déléguée" à... un contrôleur.
C’est plus complexe que cela. Et effectivement mes projectiles peuvent rebondir sur un obstacle disparaitre ou être à tête chercheuse.
C'est bien pour cela que tu ne peux pas limiter ta réflexion au seul passage d'informations entre ton projectile et la capacité de tir qui a provoqué sa création.
La "transmission d'informations" vers et depuis le projectile doit être gérée dans son ensemble, par "quelque chose" qui puisse avoir connaissance de l'ensemble de l'environnement dans lequel le projectile évolue (la capacité de tir faisant partie de cet environnement
), quitte à ce qu'il ne voie le projectile que comme "un projectile, sans précision" et quitte à ce que ce "quelque chose" puisse mettre chaque projectile en relation avec la capacité de tir qui en a provoquer la création.
Le "quelque chose" dont je parle n'est ni le projectile, ni la capacité de tir (bien qu'il ait connaissance des deux
) et se classe dans la catégorie des contrôleurs: une classe qui peut vérifier les états de certains objets dont elle a connaissance et modifier l'état d'autres objet en conséquence si le conditions pour ce faire sont vérifiées 
J’ai opté pour une méthode de gestion qui ressemble à de l’inversion de contrôle : il n’y a pas de grand scrutateur qui manage mais chaque projectile se gère et notifie les étapes importantes de sa vie à qui de droit. C’est ce que j’appelle le comble de l’inspecteur ….
Sauf que tu donnes là une responsabilité qu'il ne devrait pas avoir à ton projectile.
Les grandes étapes d'un projectile (pris de manière tout à fait générale
) sont: je pars, je touche, je meure "de ma belle mort" (mais sans rien avoir touché
).
Mais ce n'est pas au projectile de prévenir qui que ce soit, c'est à cette "autre chose" dont j'ai parlé plus haut, d'autant plus que la capacité de tir n'est qu'une des choses qui peut devoir être tenue au courent de certaines étapes spécifiques 
Oui mais non, pour les pointeurs de fonction en JEE il n’ y a ni le paradigme de C++ ni celui de C# et le système de gestion des évènements est plus fouillis.
Je ne crois pas qu'il soit pertinent de lancer ce genre de débat dans cette discussion en particulier.
Mais je peux t'assurer que, sans entrer dans les détails spécifiques, le "mode de pensée" adopté en C# est, très certainement, beaucoup plus proche de celui que l'on adopte en java que de celui qu'on adopte en C++.
Avec des différences notoires, je n'en disconvient absolument pas, mais le fait général reste malgré tout
Partager