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 :

Vecteur d'objets constants


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    228
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 228
    Points : 102
    Points
    102
    Par défaut Vecteur d'objets constants
    Bonjour,

    J'aimerais créé une méthode qui prends en paramèetre un vecteur créé par l'appelant, rempli d'objets que je ne souhaite pas modifiable par l'appelant.

    de mon point de vu la signature est celel ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    bool toto (std::vector<const CMonObjet>& liste)
    Ensuite je cherche à utiliser cette methode, et c'est la que ça se corce.
    Impossible d'initialiser la variable d'appel...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    int main()
    {
    std::vector<const CMonObjet> liste;
    }
    Comment fait on cela ?

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Ceci compile parfaitement chez moi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include <vector>
     
    class A 
    {
    public:
    	A();
    private:
    	int x;
    };
     
    A::A() : x(1) {};
     
    bool toto( std::vector<const A>& liste )
    {
    	return true;
    }
     
    int main(int argc, char *argv[])
    {
    	std::vector<const A> liste;
    	const A a1;
    	const A a2;
    	liste.push_back(a1);
    	liste.push_back(a2);
    	toto(liste);
    	return 0;
    }
    Find me on github

  3. #3
    Membre habitué Avatar de nowahn
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 84
    Points : 150
    Points
    150
    Par défaut
    Bonjour,

    Par contre, ceci ne compile pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ...
     
    bool toto(std::vector<const A>& liste)
    {
       return true;
    }
     
    ...
     
    std::vector<A> liste; // pas de const
     
    ...
     
    toto(liste);
     
    ...
    Qu’est-ce que tu veux faire exactement Chronos ?

    Je ne crois pas qu’il soit possible de passer par référence un conteneur vers un conteneur de membres constants.
    Plusieurs solutions :
    • Passer le vecteur par valeur, mais ça provoquera la copie du vecteur et de tous ses éléments (pas testé, mais à priori ça doit marcher).
    • Prendre une référence de vecteur de membres non constants.
    • Prendre une référence sur un vecteur constant, mais ça empêche de modifier le vecteur lui-même dans la fonction, ce qui n’est peut-être pas ce que tu veux.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    La question que je voudrais poser avant toute chose, c'est:

    Tes objets sont ils toujours constants et de manière systématique, ou ne souhaites tu qu'ils soient constants que le temps de l'exécution de la fonction

    Il serait en effet dommage de se trouver dans une situation dans laquelle tu devrais commencer par copier l'ensemble d'une collection (non constante) d'objets (non constants) dans une collection d'objet constants avant de pouvoir passer cette copie à une fonction, alors que, si tu transmet "simplement" la collection d'objets non constants sous la forme d'une référence constante, et que tu décides d'utiliser les itérateur, tu ne pourra de toutes manière utiliser que... le const_iterator qui assure la constance des éléments de la collection

    La remarque que je voudrais faire ensuite, c'est que tu aurais largement intérêt à transmettre un écart ("range" en anglais) commençant au premier élément de ta collection et terminant juste après le dernier.

    Ainsi, tu pourrais parfaitement envisager de faire en sorte que ta fonction appelée prenne la forme de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    bool foo(typename std::vector<Object>::const_iterator b, 
             typename std::vector<Object::const_iterator e)
    {
        while (b!=e)
        {
            /* ce qui doit être fait... un const_iterator assure la constance de
             * l'élément itéré et s'utilise comme un pointeur (avec * et -> )
             */
           ++b;
        }
    }
    qui serait utilisée sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main()
    {
        std::vector<Object> tab;
        /* on remplis le tableau d'objets
         * ...
         * avant d'invoquer la fonction grâce à
         */
        foo(tab.begin(),tab.end());
    }
    Il y aurait même moyen, grâce à la programmation générique, d'envisager le fait que les objets puissent se trouver dans d'autres sortes de collection (piles, files, listes), de manière à ne pas imposer à l'utilisateur le choix d'une collection qui n'est pas *forcément* le meilleur, et, d'autre part, de te laisser justement l'occasion de décider que, effectivement, l'utilisation d'un std::vector n'est peut être pas la meilleure solution.

    La fonction ressemblerait alors à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <iterator>
    bool foo(iterator b, iterator e)
    {
        while (b!=e)
        {
            /* ce qui doit être fait... un const_iterator assure la constance de
             * l'élément itéré et s'utilise comme un pointeur (avec * et -> )
             */
           ++b;
        }
    }
    Si tu veilles, effectivement, à n'appeler que des fonctions membres constantes dans cette fonction, le fait que les différents objets soient effectivement constants ou non n'aura plus d'importance

    Cette fonction aura cependant l'énorme avantage de fonctionner avec un maximum de possibilités, le tout, sans avoir une seule ligne de code supplémentaire à écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    int main()
    {
        /* elle fonctionnera avec un vector d'objet constants */
        std::vector<Object const> tabConst;
        foo(tabConst.begin(); tabConst.end());
        /* avec un vector d'objet non constants */
        std::vector<Object> tab;
        foo(tab.begin(),tab.end());
        /* avec une std::list */
        std::list<Object /* const */> l;
        foo(l.begin(),l.end());
        /* avec une pile */
        std::stack<Object /* const */> s;
        foo(s.begin(),s.end());
        /* avec une file */
        std::dequeue<Object /* const */> d;
        foo(d.begin(),d.end());
        /* avec un set (tableau associatif trié dans lequel la clé est l'objet
         * lui-même)
         * 
         * les itérateurs récupérés sont automatiquement constant avec 
         * cette collection
         */
        std::set<Object > st;
        foo(st.begin(),st.end());
        /*...*/
        return 0;
    }
    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

Discussions similaires

  1. Réponses: 10
    Dernier message: 22/09/2008, 10h23
  2. Vecteur d' objets
    Par Mookie dans le forum Langage
    Réponses: 4
    Dernier message: 30/09/2006, 19h00
  3. Réponses: 10
    Dernier message: 04/07/2006, 20h57
  4. [MFC] Manipuler un vecteur d'objets
    Par Yellowmat dans le forum MFC
    Réponses: 4
    Dernier message: 13/07/2005, 14h37
  5. Réponses: 6
    Dernier message: 03/09/2003, 10h29

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