Question

J'ai écrit un analyseur de fichier pour un jeu que je vous écris pour le rendre facile pour moi de changer différents aspects du jeu (des choses comme les données de caractère / stade / collision). Par exemple, je pourrais avoir une classe de caractères comme ceci:

class Character
{
public:
    int x, y; // Character's location
    Character* teammate;
}

Je créé mon analyseur pour lire à partir d'un fichier de la structure de données avec une syntaxe similaire à C ++

Character Sidekick
{
    X = 12
    Y = 0
}

Character AwesomeDude
{
    X = 10
    Y = 50
    Teammate = Sidekick
}

Cela va créer deux structures de données et les mettre dans un map<std::string, Character*>, où la chaîne clé est le nom que je lui ai donné (dans ce cas Sidekick et AwesomeDude). Quand mon analyseur voit un pointeur vers une classe, comme le pointeur de son coéquipier, il est assez intelligent pour regarder la carte pour chercher le pointeur sur cette structure de données. Le problème est que je ne peux pas déclarer son coéquipier Sidekick être AwesomeDude parce qu'il n'a pas été placé dans la carte de caractère encore.

Je suis en train de trouver la meilleure façon de résoudre ce afin que je puisse avoir mes structures de données des objets de référence qui n'ont pas encore été ajoutés à la carte. Les deux solutions les plus simples que je peux penser sont (a) ajouter la possibilité de transmettre déclarer des structures de données ou (b) ont l'analyseur lu dans le fichier deux fois, une fois pour remplir la carte avec des pointeurs vers des structures de données vides et une seconde fois et passer par les remplir.

Le problème avec (a) est que je peux aussi décider quel constructeur de faire appel à une classe, et si je déclare en avant quelque chose que je dois avoir le constructeur soit en dehors du reste des données, ce qui pourrait être source de confusion . Le problème avec (b) est que je pourrais vouloir déclarer Sidekick et AwesomeDude dans leurs propres fichiers. Je dois faire mon analyseur soit en mesure de prendre une liste de fichiers à lire plutôt qu'un seul à la fois (ce qui est pas si mal je suppose, bien que parfois je pourrais vouloir obtenir une liste de fichiers à lire à partir d'un fichier). (B) présente également l'inconvénient de ne pas être en mesure d'utiliser des structures de données déclarées plus tard dans le constructeur lui-même, mais je ne pense pas que ce soit une affaire énorme.

Dans quel sens ressemble à une meilleure approche? Y at-il une troisième option, je ne l'ai pas pensé? Il semble que il devrait y avoir une solution intelligente à ce avec des références de pointeur ou de liaison ou quelque chose ...: - / Je suppose que cela est un peu subjective basée sur les fonctions que je veux me donner, mais toute entrée est la bienvenue.

Était-ce utile?

La solution

Lorsque vous rencontrez la référence pour la première fois, stocker simplement comme référence. Ensuite, vous pouvez mettre le caractère ou la référence, ou quoi que sur une liste de « références qui doivent être résolus plus tard ».

Lorsque le fichier est fait, courir à travers ceux qui ont des références et de les résoudre.

Autres conseils

Eh bien, vous avez demandé une troisième option. Vous ne devez pas utiliser XML, mais si vous suivez la structure suivante, il serait très simple d'utiliser un analyseur SAX pour construire votre structure de données.

En tout cas, au lieu de référencer un coéquipier, chaque personnage fait référence à une équipe (équipe bleue dans ce cas). Cela découpler la question de la référence circulaire. Assurez-vous d'énumérer les équipes avant les personnages.

<team>Blue</team>

<character>
    <name>Sidekick</name>
    <X>12</X>
    <Y>0</Y>
    <teamref>Blue</teamref>
</character>

<character>
    <name>Sidekick</name>
    <X>10</X>
    <Y>50</Y>
    <teamref>Blue</teamref>
</character>

Personnellement, je partirais avec b). Fractionnement votre code dans les classes Parser et Validator, les deux fonctionnant sur la même structure de données. Le Parser lire et analyser un fichier, le remplissage de la structure de données et le stockage des références d'objet que leurs noms textuelles, laissant le vrai pointeur null dans votre structure pour l'instant.

Lorsque vous avez terminé le chargement des fichiers, utilisez la classe Validator pour valider et résoudre les références, remplissant les pointeurs « vrais ». Vous voulez examiner comment structurer vos données pour faire ces recherches agréable et rapide.

Will a dit exactement ce que j'allais écrire. Il suffit de garder une liste ou quelque chose avec les références non résolues.

Et ne pas oublier de jeter une erreur s'il y a des références non résolues une fois que vous aurez fini de lire le fichier = P

Au lieu de stocker l'objet de caractères dans votre carte, stocker un proxy pour le caractère. La procuration de contenir un pointeur vers l'objet du personnage réel lorsque l'objet est chargé. Le type de personnage :: coéquipier sera changé à ce type de proxy. Lorsque vous lisez une référence qui ne sont pas déjà dans votre carte, vous créez un proxy et d'utiliser le proxy. Lorsque vous chargez un caractère que vous avez déjà un proxy vide sur la carte, le remplir avec votre personnage nouvellement chargé. Vous pouvez également ajouter un compteur de garder une trace de combien de proxy vide que vous avez dans la carte afin de savoir quand tous les personnages mentionnés ont été chargés.

Une autre couche de indirection .... il fait toujours la programmation plus facile et plus lent.

L'une des options serait de renverser l'obligation. La carte est chargée de remplir la référence

template<T> class SymbolMap // I never could rememeber C++ template syntax
{
   ...

   /// fill in target with thing name
   /// if no name yet, add it to the list of thing that will be name
   void Set(T& target, std::string name);

   /// define name as target
   /// go back and fill in anything that needs to be name
   void Define(T target, std::string name);

   /// make sure everything is resolved
   ~SymbolMap()
}

qui n'interagissent bien avec la valeur / sémantique en mouvement, mais je suppose que pas beaucoup la volonté.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top