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 :

iterateur et encapsulation


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut iterateur et encapsulation
    Bonjour à tous,

    J'ai une classe Individu et une classe Menage. Un ménage est composé de plusieurs individus. Je stocke donc dans ma classe ménage un vecteur d'adresses d'individus. Je voudrais pouvoir itérer sur ce vecteur sans que l'utilisateur de ma classe puisse modifier directement mon vecteur mais il faudrait qu'il puisse appeler les fonctions membre de la classe Individu. Voici mon code actuel:
    Classe Individu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Individu
    {
    private:
        string _strName;
    public:
        void setName(const string& name) { _strName = name; }
    };
    La classe Menage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    typedef vector<Individu*>::iterator iteratorIndiv;
     
    class Menage
    {
    private:
        vector<Individu*> _vctIndiv;
    public:
     
        iteratorIndiv begin() { return _vctIndiv.begin(); }
     
        void ajouterIndiv (Individu& ind) { _vctIndiv.push_back(&ind); }
    };
    Donc en résumé, je voudrais que l'on ne puisse pas faire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Individu ind1, ind2;
    Menage m;
    m.ajouterIndiv (ind1);
    *(m.begin()) = &ind2; //pas possible
    mais que l'on puisse faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Individu ind1;
    Menage m;
    m.ajouterIndiv (ind1);
    (*(m.begin()))->setName("toto"); //possible de modifier les éléments du vecteur
    C'est sans doute tout bête mais là je coince...

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Par défaut
    dans ce cas là propose juste l'interface réduite dans ménage qui permet de modifier les individus? sans proposer l'accès à un iterateur qui permettra de faire ce que l'on veut avec.

  3. #3
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    ... ou utilise un const_iterator.

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Déjà, il y a une mauvaise pratique dans ton code: ta fonction ajouterIndiv() devrait prendre un pointeur en paramètre, ou mettre une copie de l'individu dans le vecteur: Il est hautement déconseillé de "promouvoir" une référence en pointeur permanent.

    Pour le reste, la réponse de Sylvain est bonne: Un const_iterator interdira de modifier le pointeur, tout en laissant modifiable l'objet pointé.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut
    Merci pour cette réponse, ça marche nickel. Effectivement Médinoc, j'avais jamais trop fait attention mais c'est vrai que promouvoir une référence en pointeur permanent peut avoir de graves conséquences. Par contre, je sais pas trop comment contrer ce problème: pour éviter des copies dans tout les sens, je n'alloue mes objets qu'une seule fois au chargement des données (par le biais d'une classe "superviseur" qui stocke le vecteur des individus et des ménages). Ensuite les liens se font par le biais de pointeurs. Je peux toujours effectivement changer le prototype de ma fonction ajouterIndiv mais lors de l'appel je ferais un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Individu ind;
    Menage m;
    m.ajouterIndiv(&ind);
    Ce qui ne va pas changer le "risque" que je prend. Comment fais tu pour charger tes données et gérer les liens sans "prendre de risques" sur la validité de tes pointeurs (si tes liens entre classes sont gérés par pointeurs)

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Citation Envoyé par Médinoc Voir le message
    Déjà, il y a une mauvaise pratique dans ton code: ta fonction ajouterIndiv() devrait prendre un pointeur en paramètre, ou mettre une copie de l'individu dans le vecteur: Il est hautement déconseillé de "promouvoir" une référence en pointeur permanent.
    Je ne vois pas très bien ce que ça change, techniquement rien en tous cas, après tu peux toujours avoir une convention implicite dans ton code qui sous-entend que passer par pointeur transfert la propriété et par référence non, mais c'est quand même un peu bizarre.

    Pour moi ça n'a pas d'importance, j'utilise uniquement des pointeurs à la place de références quand je veux signaler que la valeur 0 est acceptée.
    Les questions de transmission de propriétés je les gère avec des pointeurs intelligents. Si l'interface présente une référence (ou un pointeur) c'est que l'appelant reste responsable et donc soit devra désenregistrer l'élément (en appelant un 'retirerIndiv' par ex) soit devra s'assurer de la destruction dans le bon ordre ('Menage' avant les 'Individu').

    MAT.

  7. #7
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Mat007 Voir le message
    Salut,
    Je ne vois pas très bien ce que ça change, techniquement rien en tous cas
    Si, quand même:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void f(Menage& m)
    {
      Individu ind;
      m.ajouterIndiv(ind);
    }
    int main()
    {
      Menage m;
      f(m);
      m.begin()->setName("test");
    }
    Au moins, le passage par pointeur donne un indice fort: "j'ai besoin de l'adresse de l'objet, donc tu dois faire en sorte qu'il existe tant qu'il est présent dans la liste". Tandis que le passage par référence semble indiquer qu'une copie va être effectuée.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

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

Discussions similaires

  1. Réponses: 31
    Dernier message: 30/03/2006, 16h57
  2. ecrire un iterateur pour une classe
    Par Blowih dans le forum C++
    Réponses: 2
    Dernier message: 15/11/2004, 19h19
  3. STL iterateur pour queue
    Par Mathieu.Nanoux dans le forum SL & STL
    Réponses: 2
    Dernier message: 05/11/2004, 00h35
  4. Encapsulation graphique d'un outil en ligne de commande
    Par Leishmaniose dans le forum Composants VCL
    Réponses: 3
    Dernier message: 12/11/2003, 11h59
  5. [MFC](encapsulation ADO) ou placer le code
    Par philippe V dans le forum MFC
    Réponses: 2
    Dernier message: 13/06/2002, 14h58

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