147 votes

Créer mes propres itérateurs

J'essaie d'apprendre le C++, alors pardonnez-moi si cette question démontre un manque de connaissances de base, vous voyez, le fait est que j'ai un manque de connaissances de base.

J'ai besoin d'aide pour savoir comment créer un itérateur pour une classe que j'ai créée.

J'ai une classe "Shape" qui possède un conteneur de points. J'ai une classe 'Piece' qui fait référence à un Shape et définit une position pour le Shape. Piece n'a pas de Shape, il ne fait que référencer un Shape.

Je veux que l'on ait l'impression que la pièce est un conteneur de points qui sont les mêmes que ceux de la forme qu'elle référence, mais avec le décalage de la position de la pièce ajouté.

Je veux être en mesure d'itérer à travers les points de Piece comme si Piece était un conteneur lui-même. J'ai fait un peu de lecture et je n'ai rien trouvé qui m'ait aidé. Je serais très reconnaissant pour toute indication.

6 votes

L'affichage d'un exemple de code aiderait à décrire ce que vous faites mieux qu'un simple texte en anglais.

3 votes

La création d'itérateurs personnalisés est probablement no un haut de base, intermédiaire au moins.

63voto

Konrad Rudolph Points 231505

/EDIT : Je vois, un itérateur propre est en fait nécessaire ici (j'ai mal lu la question en premier). Néanmoins, je laisse le code ci-dessous car il peut être utile dans des circonstances similaires.


Un itérateur propre est-il vraiment nécessaire ici ? Il suffit peut-être de transmettre toutes les définitions requises au conteneur contenant les points réels :

// Your class `Piece`
class Piece {
private:
    Shape m_shape;

public:

    typedef std::vector<Point>::iterator iterator;
    typedef std::vector<Point>::const_iterator const_iterator;

    iterator begin() { return m_shape.container.begin(); }

    const_iterator begin() const { return m_shape.container.begin(); }

    iterator end() { return m_shape.container.end(); }

    const_iterator end() const { return m_shape.const_container.end(); }
}

Cela suppose que vous utilisez un vector en interne mais le type peut facilement être adapté.

0 votes

Peut-être veut-il utiliser l'algorithme STL ou les fonctionnalités fonctionnelles contre sa classe...

2 votes

La question originale dit en fait que l'itérateur du conteneur de pièces doit modifier les valeurs lorsqu'il les renvoie. Cela nécessiterait un itérateur séparé, même s'il devrait probablement être hérité ou obtenu d'une autre manière principalement à partir de l'original.

0 votes

Ce qui est bien avec mon code, c'est qu'il puede être utilisé par les algorithmes STL.

42voto

Roel Points 9657

Vous devriez utiliser Boost.Iterators. Il contient un certain nombre de modèles et de concepts pour implémenter de nouveaux itérateurs et des adaptateurs pour les itérateurs existants. J'ai écrit un article sur ce même sujet Il est publié dans le magazine ACCU de décembre 2008. Il traite d'une solution élégante (selon moi) pour résoudre exactement votre problème : exposer les collections de membres d'un objet, en utilisant Boost.Iterators.

Si vous souhaitez utiliser uniquement le stl, la fonction Livre Josuttis contient un chapitre sur l'implémentation de vos propres itérateurs STL.

3 votes

Juste une petite remarque : Le livre parle de la bibliothèque standard C++, et non de la STL - ces deux éléments sont différents, mais sont souvent confondus (je suis/étais coupable, moi aussi).

21voto

Abhay Points 4268

Ici Conception d'un conteneur personnalisé de type STL est un excellent article qui explique certains des concepts de base sur la façon dont une classe de conteneur de type STL peut être conçue, ainsi que la classe d'itérateur correspondante. L'itérateur inverse (un peu plus difficile) est laissé comme un exercice :-)

HTH,

15voto

gbjbaanb Points 31045

Vous pouvez lire ceci article ddj

En gros, héritez de std::iterator pour que la plupart du travail soit fait pour vous.

4 votes

Notez que std::iterator est marqué déprécié à partir de C++17.

1voto

Diomidis Spinellis Points 8417

La solution à votre problème ne consiste pas à créer vos propres itérateurs, mais à utiliser les conteneurs et itérateurs STL existants. Stockez les points de chaque forme dans un conteneur comme vector.

class Shape {
    private:
    vector <Point> points;

Ce que vous faites à partir de là dépend de votre conception. La meilleure approche est d'itérer à travers les points dans les méthodes à l'intérieur de Shape.

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

Si vous avez besoin d'accéder aux points en dehors de Shape (ce qui pourrait être la marque d'une conception déficiente), vous pouvez créer dans Shape des méthodes qui renverront les fonctions d'accès aux itérateurs pour les points (dans ce cas, créez également un typedef public pour le conteneur de points). Consultez la réponse de Konrad Rudolph pour plus de détails sur cette approche.

3 votes

Il devra encore créer son propre itérateur qui transmet les demandes de pièces aux formes qui se trouvent dans ces pièces. Les itérateurs personnalisés sont un outil formidable dans ce cas, et très élégant à utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X