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 :

[Débutant] Autre question sur Const


Sujet :

C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2006
    Messages
    572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 572
    Points : 631
    Points
    631
    Par défaut [Débutant] Autre question sur Const
    Bonjour,

    J'ai un problème à me faire à toutes les subtilités de const.

    Soit une classe A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class A
    {
      public :
        A() : a(0) {};
        void setA(int a){a_ = a;}
        int getA() const {return a;}
     
      private :
        int a_;
    }
    Quel est l'effet de const sur la class A ? Plus particulièrement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int main()
    {
      const A var;
     
      var.setA(10); // Est ce que cette ligne est valide ?
    }
    Merci

  2. #2
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Bonjour,

    As-tu essayé de compiler, avant de poser la question ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2006
    Messages
    572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 572
    Points : 631
    Points
    631
    Par défaut
    Non, malheureusement, je n'ai rien pour faire ça là d'où je suis. Je révise mon c++ en vue d'entretiens sans jamais pouvoir en compiler, du coup, je pose parfois des questions un peu bête.

    La réponse à ma question est donc évidente avec un compilateur, merci, je verrais ça ce soir.

    Désolé

  4. #4
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Ca ne compile tout simplement pas : tu as déclaré ton objet const donc elle ne compilera que si le code appelle des methods const aussi.

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

    Informations professionnelles :
    Activité : aucun

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

    Une méthode constante n'applique la constance qu'au sein du code qui l'implémente.

    il s'agit d'un "contrat" que tu passe au compilateur en lui disant "je m'engage formellement à ne pas modifier la classe dans cette méthode".

    Cela sous entend que seules les méthodes déclarées constantes pourront accéder à une variable elle-même déclarée constante.

    Pour t'aider à comprendre le principe:

    Les conteneurs triés set et map de la STL utilisent une clé pour effectuer le tri, qui peut être de n'importe quel type, pour autant qu'il existe la possibilité d'effectuer une comparaison "plus petit que".

    Or, tu te rend bien compte que, si tu modifie une variable qui sert de clé pour le tri, tu va littéralement "aller foutre le B..." dans le système de tri.

    Mais il n'y a pourtant rien qui t'empêche de vouloir récupérer cette clé, par exemple, pour utiliser les valeurs qu'elle représente pour d'autres choses.

    Pire, tant que tu utilise le type en question sans t'en servir comme d'une clé de tri, rien ne t'empêche - a priori - de vouloir la modifier à ton aise, en créant des méthodes que l'on appelle "mutateurs".

    C'est la raison pour laquelle les conteneurs triés renvoient de manière systématique une référence constante sur la clé lorsque tu leur demande de la renvoyer.

    Et, pour s'assurer que l'élément constant ne sera pas modifié, les seules méthodes que tu pourra appeler au départ de ces références constantes seront... les méthodes qui se seront engagées à ne pas modifier la variable

    Un petit exemple pour comprendre:

    Soit une class MyInt qui permet de manipuler... des entiers. Cette classe est destinée à servir de clé dans une std::map ou dans un std::set (par exemple).

    Mais elle est aussi destinée à travailler de manière tout à fait normale, simplement en "cachant" le fait que l'on travaille en réalité sur... des entiers.

    Elle pourrait donc se représenter sous la forme de
    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
    29
    30
    31
    32
    33
    34
    35
    36
    class MyInt
    {
        public:
            /* le constructeur */
            MyInt(int i = 0):i(i){}
            /* nous pouvons laisser au compilateur le soin d'implémenter les
             * autres méthodes du Big Four
             */
            /* les opérateur d'incrémentation et de décrémentation
             * ces opérateurs modifient la classe
             */
            MyInt& operator++()
            {
                ++i;
                return (*this);
            }
            MyInt& operator--()
            {
                --i;
                return (*this);
            }
            /* Les opérateurs de comparaison
             * Ils ne modifient pas la classe, et s'y engagent
             */
            bool operator==(const MyInt& rhs) const {return i==rhs.i;}
            bool operator<(const MyInt& rhs) const {return i<rhs.i;}
            /* je pourrais aussi définir >, >=, <= et != ;) */
            /* la possibilité d'obtenir la valeur
             * cela ne modifie pas la classe, et s'y engage
             */
            int value() const{return i;}
            /* et le mutateur, pour modifier carrément la valeur de i */
            void setValue(int newi){i=newi;}
        private:
            int i;
    };
    Je peux donc tout à fait écrire un code proche de
    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
    int main()
    {
        MyInt my(5);
        ++my;
        std::cout<< my.value()<<std::endl;
        MyInt m2(0);
        while(m2<my)
        {
            std::cout<<"valeur de m2 "<<m2.value()<<" plus petit... incrementons"
                     <<std::endl;
            ++m2;
        }
        std::cout<<" m2 et my sont egaux: m2 = "<<m2.value()
                 <<" my = "<<my.value()<<std::endl;
        return 0;
    }
    Mais je pourrais aussi vouloir utiliser cette classe dans un set, par exemple, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main()
    {
        std::set<MyInt> s;
        /* placons des éléments dans le set */
        for(int i= 0;i<10;++i)
            s.insert(MyInt(i));
        /* et utilisons les */
        for(std::set<MyInt>::iterator it=s.begin();it!=s.end();++it)
        {
            //l'utilisation de chacun des éléments du set */
        }
        return 0;
    }
    Tu te rend tout de suite compte que si, dans la fameuse boucle for(std::set<MyInt>::iterator it=s.begin();it!=s.end();++it) , tu venais à modifier l'objet en lui-même,(par exemple avec un ++(*it) ) tu mettrais un sacré b dans le tri

    C'est la raison pour laquelle it fournit une référence constante sur l'objet, et que tu ne pourra donc appeler que les méthodes qui se seront engagées à ne pas le modifier.

    Autrement dit, les operateurs ++ et -- ainsi que la méthode setValue seront refusés à la compilation, mais les opérateurs de conversion et la méthode value - qui se sont engagés à ne pas modifier l'objet - pourront être appelés sans problème sous une forme qui pourrait prendre la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if((*it)->value()<10)
        std::cout<<it->value()<<std::endl

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Euh, je crois que seuls les const_iterator fournissent une référence constante, non?
    Ou bien, les conteneurs triés comme set et map sont des cas particuliers ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Les conteneur triés sont un cas particulier: la clé est une référence constante...

    Normalement, si tu fait un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    { 
        std:: map<std::string, Type> lamap;
        /*...*/
        it =lamap.begin();
        (*it).first+="salut";
        return 0;
    }
    le compilateur te plantera parce que tu utilise une fonction qui désactive les qualificateurs

    Le set a donc ceci de particulier que son iterateur réagit comme un const_iterateur et que, pour modifier un élément - qui est la clé de tri - tu est obligé de copier l'élément en question, de le supprimer, et de modifier la copie, avant de l'insérer à nouveau.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    OK, merci!

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Pour que tu comprenne le pourquoi:

    La map et le set travaille sous la forme d'un arbre binaire, comme tu le sais.
    c'est à dire que la recherche va s'effectuer... sur la clé avec un algorithme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    si (element< recherche)
        aller à gauche
    sinon si (recherche > element)
        aller à droite
    sinon
        l'élément est trouvé
    Si l'arbre binaire permettait de "bousiller" la clé en la modifiant, tu courerais le risque de voir l'élément se trouver au noeud "plus petit que" de l'élément précédent de l'arbre, alors que, l'évaluation de la clé bousillée devrait la placer au noeud "plus grand que", et inversement.

    Il est donc logique qu'il rendre la clé constante de manière silencieuse

  10. #10
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2006
    Messages
    572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 572
    Points : 631
    Points
    631
    Par défaut
    Superbe réponse, merci

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/03/2008, 23h28
  2. [débutant] 2 questions sur les formulaires
    Par pepper18 dans le forum IHM
    Réponses: 3
    Dernier message: 19/04/2007, 11h50
  3. D'autres questions sur la sécurité
    Par mathias dans le forum Sécurité
    Réponses: 1
    Dernier message: 18/08/2006, 14h41
  4. Débutant RCP - Question sur l'architecture
    Par LoloBebop dans le forum Eclipse Platform
    Réponses: 11
    Dernier message: 07/06/2006, 11h35
  5. [Débutant] Deux questions sur la conversion (cast)
    Par kloss dans le forum Langage
    Réponses: 7
    Dernier message: 18/02/2006, 19h46

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