
Envoyé par
Doudoupe
De là j'ai complètement ré-écrit mon code en suivant cette représentation.
Seulement je me heurte à des complexités du langage (C ou C++), car effectivement je ne connais pas certaines notions. Par exemple, quand je vois : std::list<Bomb*>::iterator it=bombs_.begin() , j'ai du mal à comprendre comment ça fonctionne... Et c'est pas vraiment sur la version papier de mon prog.
Bon, on va commencer par le commencement:
C++ autorise un paradigme nommé "programmation générique", et toutes les collections fournies par le standard (vector, stack, queue, list, set, map, ...) utilisent ce paradigme.
L'idée de ce paradigme est simple: si on ne sait pas encore (au moment de créer ces collections) quel type de données nous mettrons dedans, nous savons, par contre, comment les différentes collections vont les manipuler:
Qu'il s'agisse d'une file de voitures, d'une file d'attente aux caisses d'un magasin ou d'une file d'attente pour passer chez le médecin, la manière dont nous en manipulerons les éléments sera, quoi qu'il arrive, toujours la même: les nouveaux arrivants se placeront "en fin de file", et le premier élément "servi" sera celui qui se trouve... "en début de file" et, une fois celui-ci servi, il quittera la file parce qu'il n'a plus rien à y faire 
C'est pour cela que nous obtenons l'écriture assez bizare de std::list<Bomb*> (std::list représente le type de collection, et donc la manière dont on manipule les éléments, <Bomb*> indique que nous nous apprêtons à... manipuler des pointeurs sur Bomb
)
Lorsque l'on manipule des collections d'objets, on se rend compte qu'il faut pouvoir... parcourir l'ensemble de la collection, en respectant certaines règles propre au type de la collection envisagée.
Pour ce faire, chaque type de collection défini ce que l'on appelle un "itérateur", qui n'est, pour faire simple, qu'un "enrobage" de l'objet manipulé de manière à pouvoir passer à l'élément suivant et / ou précédent de la collection.
Seulement, les règles permettant de passer d'un élément à l'élément suivant et / ou à l'élément précédent d'une collection dépendent... du type de la collection utilisée.
Les tableaux associatifs (set et map, par exemple), qui présentent les différents éléments triés de manière automatique, vont utiliser un système "dichotomique", c'est à dire que chaque élément est relié à un élément "plus petit" et à un élément "plus grand" (enfin, s'il y en a un).
Ce principe permet, quand les éléments sont correctement triés, de retrouver une valeur donnée parmis 255 valeurs différentes en maximum... 8 tests successifs 
Le système FIFO (la std::queue) quant à lui, gère le premier élément ajouté, et le retire de la file, quand le système LIFO gère le dernier élément ajouté avant de le retirer et quand une liste permet de gérer les éléments de manière séquentielle (le premier avant le deuxième qui est lui-même géré avant le quatrième, etc) et qui permet, pourquoi pas, de parcourir les éléments "dans les deux sens" (du premier ajouté au dernier, ou vice versa), voire, d'insérer un élément entre deux éléments déjà présents.
C'est pourquoi, la classe qui sert d'itérateur est... imbriquée dans la collection.
Une classe imbriquée ressemble à quelque chose comme
1 2 3 4 5 6 7 8
| class MaClass
{
public:
class Imbriquee
{
/*...*/
};
}; |
Cela implique que, pour arriver à la classe imbriquée, il faut passer par... la classe dans laquelle elle est imbriquée, en utilisant l'indicateur de portée ::.
Je ne peux donc déclarer un instance de Imbriquee que sous une forme de
Lorsque l'on écrit un code proche de
std::list<Bomb*>::iterator it;
on déclare donc une variable "it" qui est du type de la classe "iterator" que l'on trouve imbriquée dans la classe std::list. Et on prévient que l'on utilise la classe list pour gérer... des pointeurs sur Bomb.
Enfin, il y a au moins deux fonctions intéressantes dans chaque collection: begin(), qui renvoie un... itérateur sur le premier élément de la collection et end(), qui renvoie un... itérateur sur "ce qui suit le dernier élément" de celle-ci.
Comme les itérateurs de toutes les collections présentent une surcharge de l'opérateur d'incrémentation (++) qui fournit... un itérateur sur "l'élément suivant à gérer" (quel que soit le sens que l'on donne à suivant
), on peut donc écrire une boucle sous la forme de
for(std::list<Bomb*>::iterator it=laliste.begin(); it!=laliste.end(); ++it)
qui permet de commencer à parcourir la collection au "premier" élément à gérer de continuer tant que l'on a pas atteint "ce qui suit" le "dernier" élément à gérer 

Envoyé par
Pierre Dolez
Personnellement, je n'ai jamais écrit de telles choses

Et pourtant, si tu décide de ne pas te casser la tête à "réinventer" sans cesse la roue pour implémenter les différents type de collections, il y en a certaines (list, set et map en priorité) pour lesquelles tu n'a pas vraiment le choix
Partager