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 avec "const"


Sujet :

C++

  1. #1
    Membre éclairé Avatar de stracoma
    Homme Profil pro
    Médecin
    Inscrit en
    Août 2013
    Messages
    413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : Maroc

    Informations professionnelles :
    Activité : Médecin

    Informations forums :
    Inscription : Août 2013
    Messages : 413
    Par défaut methode avec "const"
    Bonsoir à vous tous.
    ce mot "const" qu'on met à la fin d'une méthode me taraude.peut être parce que je n'ai pas encore vu d'exemple où il est décisif. Prenant ce code simple:
    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
    #include <iostream>
     
    using namespace std;
    class Carre
    {
    private:
        double cote;
     
    public:
        Carre(double x):cote(x){}
        double surface() const//sans const : ne chage rien
        {
            return cote * cote;
        }
        void set_cote(double x)
        {
            cote=x;
        }
     
        double get_cote()
        {
            return cote;
        }
     
    };
    int main()
    {
        Carre carre1(25.0);
     
        cout << carre1.surface()<< endl;
        cout<<carre1.get_cote()<< endl;
        carre1.set_cote(30);
        cout<<carre1.surface()<<endl;
        cout<<carre1.get_cote()<<endl;
        return 0;
    }
    je ne trouve de différence que si j'écris la méthode surface de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double surface() 
        {
            return cote *= cote;
        }
    Pouvez vous m’écrire un petit code simple où const fait la différence. Merci

  2. #2
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Santé

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Par défaut
    Salut,

    Le mot const à la fin d'une méthode signifie que cette méthode ne modifiera pas l'objet appelant. Il faut l'utiliser au maximum pour éviter qu'un objet extérieur puisse modifier des valeurs qui n'ont pas lieux d'être.

    Ton exemple est presque bon sauf pour la méthode get_cote où il faut que tu rajoutes le mot clef const à la fin de la méthode.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Hello !

    Pour compléter ce qui a été dit plus haut, le mot const, associé à une méthode, indique au compilateur que la méthode en question n'a aucunement le droit de modifier les attributs de l'objet qui l'appelle. Par exemple, si tu écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int surface(void) const;
    int MyCLass::surface(void) const
    {
        return length * width;
    }
    Cela voudrait dire que la fonction surface n'a pas le droit de modifier les attributs de la classe MyClass. On utilise ainsi le mot clé const pour écrire ce qu'on appelle communément (dans d'autres langages) les getters. Mais l'utilisation ne se limite pas à cela. Pour éviter des erreurs de programmation, tu peux aussi faire le choix d'indiquer le mot const à chaque fois que cela a un sens : c'est-à-dire à chaque fois qu'une méthode d'une classe n'est pas sensée en modifier les attributs. Sur ce, passes une bonne journée.

  4. #4
    Membre éclairé Avatar de stracoma
    Homme Profil pro
    Médecin
    Inscrit en
    Août 2013
    Messages
    413
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : Maroc

    Informations professionnelles :
    Activité : Médecin

    Informations forums :
    Inscription : Août 2013
    Messages : 413
    Par défaut
    Si j'ai bien compris, par prudence, si on veut pas modifier les arguments , on ajout le mot const même si la foncion n'est pas censée les modifier

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par stracoma Voir le message
    Si j'ai bien compris, par prudence, si on veut pas modifier les arguments , on ajout le mot const même si la foncion n'est pas censée les modifier
    Lorqu'on ajoute le mot clé const à une méthode, le pointeur this (représentant une instance de la classe à un instant t) se comporte, lors de l'appelle de la méthode, comme un pointeur constant. Cela signifie que la dite méthode ne pourra pas modifier les attributs de la classe dans laquelle elle est définie (à moins d'utiliser les mutables). De plus, si dans une classe t'as deux méthodes qui portent la même signature mais qui diffèrent uniquement par la présence de l'identificateur const, le compilateur choisit tout seul la bonne méthode. Essayes le code suivant (j'ai mis des commentaires, n’hésites pas à les lire) :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    #include <iostream>
    #include <stdlib.h>
     
    class Class {
        /* attributes */
     
        public:
            int attr1;
            int attr2;
            mutable int attr3_mutable;
     
        /* methods */
     
        public :
            Class() : attr1(0), attr2(0), attr3_mutable(0)
            {
            }
            ~Class() {}
     
            // Cette méthode ne peut pas changer l'état du pointeur this
            void updateAttributes(int a1, int a2) const
            {
                std::cout << "methode " << __func__ << " const" << std::endl;
     
                // décommentes ceci pour voir
                /*attr1 = a1;
                attr2 = a2;*/
     
                // un attribut mutable peut être cependant modifié
                attr3_mutable = 1;
            }
     
            void updateAttributes(int a1, int a2)
            {
                std::cout << "methode " << __func__ << std::endl;
     
                attr1 = a1;
                attr2 = a2;
                attr3_mutable = 1;
            }
    };
     
    int main()
    {
        std::cout << "On a deux objets : l'un declare const et l'autre non" << std::endl;
        std::cout << "Remarques que le methode appelee n'est pas toujours la meme" << std::endl;
        std::cout << "-----------------------------------------------------------\n" << std::endl;
     
        Class c1_notConst;
        c1_notConst.updateAttributes(0, 0);
     
        const Class c2_const;
        c2_const.updateAttributes(0, 0);
     
        return 0;
    }
    Bon courage et n'hésites pas si t'as d'autres questions !
    Dernière modification par Invité ; 22/03/2015 à 20h57.

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    307
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 307
    Par défaut
    Citation Envoyé par stracoma Voir le message
    Si j'ai bien compris, par prudence, si on veut pas modifier les arguments , on ajout le mot const même si la foncion n'est pas censée les modifier
    Cela sert aussi coté appelant, c'est une information importante on ne change pas l'objet avec une méthode "const". Ainsi si on appelle x fois une fonction membre const avec les memes arguments alors on obtiendra toujours le même résultat.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par renoo Voir le message
    [...] Ainsi si on appelle x fois une fonction membre const avec les memes arguments alors on obtiendra toujours le même résultat.
    Aïe, j'ai bien peur que non. Exemple :

    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
    class Class {
        /* attributes */
     
        public:
            mutable int x_mutable ;
     
        /* methods */
     
        public :
            Class() : x_mutable(0)
            {
            }
            ~Class() {}
     
            // Cette méthode ne peut pas changer l'état du pointeur this (sauf pour les attributs "mutable")
            int random(int n) const {
                x_mutable = n; // cette méthode, bien qu'étant déclarée const, peut modifier l'attribut x_mutable (c'est suffisant pour montrer qu'une méthode const peut permettre d'obtenir des résultats différents)
                return rand()%x_mutable ; // la méthode renvoie de plus un résultat aléatoire
            }
    };
     
    int main()
    {
        srand(time(NULL));
     
        Class c;
        std::cout << c.random(2) << std::endl;
        std::cout << c.random(2) << std::endl;
    }
    Dernière modification par Invité ; 22/03/2015 à 19h06.

  8. #8
    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
    Par défaut
    Citation Envoyé par misterFad Voir le message
    Aïe, j'ai bien peur que non.
    C'est un exemple vicieux, car tu brises volontairement le contrat. Ce serait aussi possible avec un const_cast . D'autres contre-exemple existent, comme l'appel à une fonction qui renvoie la date par exemple, dont le résultat ne sera pas le même si du temps s'écoule entre les deux appels. mutable est utile mais ne doit pas être utilisé pour modifier l'état interne de l'objet. Il sert par exemple pour mettre en place un cache, pour éviter de refaire un calcul plusieurs fois lorsqu'il est coûteux.

  9. #9
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Le gros avantage des fonctions déclarées const, c'est que ce sont les seules fonctions membres utilisables sur des références constantes.
    Je crois que c'est principalement à ce titre qu'elles sont utiles et nécessaires.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    C'est un exemple vicieux, car tu brises volontairement le contrat. Ce serait aussi possible avec un const_cast . D'autres contre-exemple existent, comme l'appel à une fonction qui renvoie la date par exemple, dont le résultat ne sera pas le même si du temps s'écoule entre les deux appels. [...]
    Effectivement, oui.

    Citation Envoyé par jblecanard Voir le message
    [...] mutable est utile mais ne doit pas être utilisé pour modifier l'état interne de l'objet. Il sert par exemple pour mettre en place un cache, pour éviter de refaire un calcul plusieurs fois lorsqu'il est coûteux.
    Je l'ignorais : j'ai encore pas mal de chose à apprendre en C++ moi.

  11. #11
    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,

    En fait, le mot clé const indique que l'état de l'objet ne peut pas être modifié.

    Rien n'empêche, la première fois que l'on appelle une fonction constante, de faire un tri (par exemple) de certaines données ou d'effectuer un calcul long et complexe dont on mettra le résultat en cache dans une variable si (et seulement si) ce tri ou le fait de changer cette valeur ne modifie pas la perception que l'on a de l'objet depuis l'extérieur (comprend : si les différents accesseurs dont on dispose ne renverront pas une valeur différente avant et après le tri ou le calcul)

    D'un autre coté, il faut savoir que les objets complexes nécessitent généralement beaucoup de temps et de ressources pour pouvoir être copiés. Et il ne faut pas aller très loin pour trouver de tels objets : la classe std::string et les différentes collections dont on dispose sont, typiquement, des objets dont la copie demande énormément de temps et de ressource. Or, dés que tu as une fonction qui prend un paramètre par valeur (sous une forme proche de void foo( Type apram)), il y a copie de la variable utilisée comme argument au niveau de la fonction appelante et c'est cette copie qui est manipulée au niveau de la fonction appelée.

    C'est, d'ailleurs, la raison essentielle pour laquelle il n'y a aucune relation entre le nom du paramètre de la fonction appelée et celui de la variable de la fonction appelante

    La solution est alors de transmettre une référence, qui agira comme un véritable alias de la variable ayant servi d'argument dans la fonction appelante. Le problème, c'est que tout ce qui arrive à un alias arrive également à la chose représentée par cet alias. Il ne faut pas s'y tromper : koala01 n'est clairement pas mon vrai nom ... Mais tout ce qui arrive à koala01 m'arrive en réalité à moi

    Cela signifie que si la fonction appelée l'état d'un de ses paramètres reçu sous la forme d'une référence, cette modification serait reportée automatiquement dans la fonction appelée. C'est parfois ce que l'on souhaite, mais cela pose très souvent plus de problème que cela n'apporte de solutions .

    Du coup, le développeur d'une fonction peut garantir à l'utilisateur de cette fonction que la fonction ne tentera pas de modifier l'état de l'objet passé par référence en déclarant cette référence constante. Et, pour assurer cette garantie, on peut faire confiance au compilateur qui sera --définitiviement -- plus buté que nous : pour lui, si un objet (ou une référence) est déclarée consante, les seules fonctions qui seront utilisables avec cet objets seront des fonctions qui garantiront ne pas essayer de modifier l'état de l'objet en question, c'est à dire :
    • N'importe quelle fonction (non membre de la classe) qui prendra l'objet l'objet par valeur (vu que c'est la copie qui sera modifiée)
    • N'importe quelle fonctin (non membre de la classe) qui prendra l'objet par référence constante
    • uniquement les fonctions membres qui s'engagent à ne pas modifier l'objet au départ duquel elle sont appelées. Cet engagement est indiqué grâce au mot clé const après la liste des paramètres requis

    Alors, je sais, les messages émis par le compilateur sont parfois "cryptiques". Mais le fait d'avoir la certitude qu'un objet ne sera pas modifié apporte une très sérieuse tranquillité d'esprit et le fait d'empêcher "chaque fois que faire se peut" qu'un objet soit modifié permet au final de rendre le code beaucoup plus robuste.

    Dés lors, et bien que cela nécessitera sans doute que tu t'habitues un peu aux messages du compilateur, le meilleur conseil que l'on puisse donner est
    Déclare tout ce que tu peux (paramètre passé par référence, fonction membre, variables, ...) comme étant constant car cela t'évitera beaucoup de problèmes liés à des modifications qui n'auraient jamais du être acceptées
    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

  12. #12
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Ca me rappelle mon résumé du C++: const toujours, raii d'abord., parodiant cause toujours, raille d'abord.
    C'est clair, c'est simple, c'est un bon moyen de ne pas trop écrire de bêtise.

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

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