IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

methode const et iterateur de vecteur


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut methode const et iterateur de vecteur
    Salut,
    j'ai une question (sans doute toute bête) mais je ne comprends pas,
    voilà c'est une methode worlds::getWorld qui compile bien.
    Mais quand je veux rajouter const (pour dire qu'elle ne modifie en rien les données de la classe), alors ca ne compile plus pourtant elle ne modifie rien, elle partours juste une vecteur membre (vWorlds) avec des iterateurs.

    voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    world* worlds::getWorld( const Uint8 id ) const
    {
    	for (std::vector<world*>::iterator it=vWorlds.begin();it!=vWorlds.end();++it)
    	{
    		if ((*it)->id==id) return (*it);
    	}
    	return NULL;
    }
    et le compilo rale sur la ligne du for parce que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    error C2440: 'initializing' : cannot convert from 'class world *const * ' to 'class world ** '
            Conversion loses qualifiers
    si quelqu'un pouvais me dire ou est l'erreur bête que j'ai commis ?,
    d'avance, merci.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    std::vector<world*>::const_iterator

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Pour compléter et comprendre la réponse de 3DArchi( qui est tout à fait juste ), il faut savoir qu'il existe généralement deux types d'itérateur sur les collections de la STL:
    1. Un itérateur "simple", nommé iterator, qui autorise parfaitement la modification de l'élément itéré (pour autant que cela ait un sens par rapport à la collection envisagée: il n'en a, par exemple aucun pour un std::set parce que la modification de l'élément met à mal le classement de celui-ci )
    2. Un itérateur constant, qui empêche toute modification de l'élément itéré.
    Le fait, c'est que, lorsque tu déclare une fonction constante, tu t'engage à ne pas modifier du tout l'objet au départ duquel tu va invoquer la fonction.

    Or, si on te donne l'occasion de modifier un élément de la collection qui fait partie de ton objet, on peut, par défaut (et en dehors de toute indication contraire de ta part) estimer que... tu modifiera l'objet en cours

    Et, comme cela irait en contradiction avec ton propre engagement de ne pas modifier l'objet, tu comprends que cela ne pourrait être toléré.

    C'est la raison pour laquelle tous les membres de l'objet en cours sont considérés comme... étant constant quand tu est dans le corps d'une fonction déclarée constante (sauf exception explicitement indiquée à l'aide du mot clé mutable).

    Le fait est qu'il existe deux versions pour les fonctions (ne modifiant jamais la collection) renvoyant un itérateur:
    • une version non constante, qui renvoie un itérateur "simple", et qui autorise donc de modifier l'objet itéré et
    • une version constante, qui renvoie un itérateur constat, et qui interdit donc toute modification de l'objet itéré
    Du coup, comme ta collection est considérée comme constante (vu que c'est un membre de l'objet en cours et que tu te trouve dans une fonction qui s'est explicitement engagée à ne pas modifier le modifier), c'est la verison constante de la fonction renvoyant un itérateur ... constant, qui sera appelée.

    Tu peux donc utiliser un itérateur "simple" (iterator) tant que tu as la certitude de ne pas être dans une situation dans laquelle ta collection serait considérée comme constante:
    • Si tu la passe par référence non constante à n'importe quel fonction (qu'elle soit libre ou membre d'une classe, et, dans ce cas, qu'elles soit constante ou non)
    • Quand tu travailles directement sur ta collection et que tu ne l'a pas déclarée constante
    Mais, en revanche, dés que ta collection est réputée (ou risque d'être réputée) constante, tu devra utiliser un... itérateur constant (const_iterator):
    • Quand ta collection est membre d'une classe et que tu est dans une fonction membre constante de cette classe
    • Quant ta collection est passée sous forme de référence constante à n'importe quelle fonction
    • Quand tu as explicitement déclaré la collection constante ce qui est, il faut l'avouer, relativement rare et peu intéressant
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    Merci,
    je comprends mieux en effet.

    je crois que je m'etais déjà fais piegé il y a quelques années, j'avais oublié.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Ceci dit, il reste un potentiellement un problème lié au retour par pointeur : rien n'empêche alors de modifier un des éléments de ton vecteur ... alors que tu as une fonction (et peut être un objet) constant. Ne serait-ce pas plutôt : world const* worlds::getWorld ?

    P.S. :
    on ne le répètera jamais assez : pointeurs intelligents !

  6. #6
    Membre éclairé
    Inscrit en
    Septembre 2003
    Messages
    391
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 391
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Ceci dit, il reste un potentiellement un problème lié au retour par pointeur : rien n'empêche alors de modifier un des éléments de ton vecteur ... alors que tu as une fonction (et peut être un objet) constant. Ne serait-ce pas plutôt : world const* worlds::getWorld ?

    P.S. :
    on ne le répètera jamais assez : pointeurs intelligents !
    oui, bon là c'est applicable en effet.
    mais imaginons (c'est pas mon cas) que je souhaite modifier l'objet en question.
    vWorlds est un vecteur de pointeur vers world.
    je ne modifirai en rien le vecteur (il n'y a qu'une adresse dedans)
    même si je modifie l'objet pointé, je ne modifie en rien ma classe worlds.
    alors que l'objet world est lui en dehors de la classe worlds (je stocke juste un pointeur qui lui n'est pas modifié ni dedans getworld ni apres).

    non ?

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par hpfx Voir le message
    oui, bon là c'est applicable en effet.
    mais imaginons (c'est pas mon cas) que je souhaite modifier l'objet en question.
    vWorlds est un vecteur de pointeur vers world.
    je ne modifirai en rien le vecteur (il n'y a qu'une adresse dedans)
    même si je modifie l'objet pointé, je ne modifie en rien ma classe worlds.
    alors que l'objet world est lui en dehors de la classe worlds (je stocke juste un pointeur qui lui n'est pas modifié ni dedans getworld ni apres).
    non ?
    si en théorie retourner un pointeur const ou non const est dépendant effectivement du contexte de ta classe et de sa relation avec ses sous éléments, en pratique (à moins que tu redéfinisses un conteneur), cela m'interpellerais de retourner un pointeur non const (en fait, j'aurais déjà poussé des cris d'orfrais à retourner un pointeur (viol de l'encapsulation), et pire, un pointeur brut )

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. iterateur sur vecteur avec objets
    Par debloc dans le forum Débuter
    Réponses: 11
    Dernier message: 04/11/2011, 19h39
  2. iterateur de vecteur 2D et erase
    Par micamused dans le forum Langage
    Réponses: 1
    Dernier message: 22/12/2010, 16h57
  3. pb avec iterateur const sur une list STL
    Par Muetdhiver dans le forum SL & STL
    Réponses: 4
    Dernier message: 14/01/2007, 16h39
  4. acces à un iterateur de vecteur par son index
    Par koala01 dans le forum C++
    Réponses: 11
    Dernier message: 25/11/2006, 10h17
  5. Réponses: 8
    Dernier message: 07/04/2006, 08h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo