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 :

getter const et passage par référence


Sujet :

C++

  1. #1
    Candidat au Club
    Homme Profil pro
    autodidacte en furie
    Inscrit en
    Août 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : autodidacte en furie

    Informations forums :
    Inscription : Août 2015
    Messages : 5
    Points : 3
    Points
    3
    Par défaut getter const et passage par référence
    Bonjour, bonjour !!

    j'étais inscrit sur un mooc c++ traitant de la poo... que je n'est pas été en mesure de finir en date et en heure ... du coup je m'y suis remis et je me retrouve donc sans personne pour me donner un coup de mainétant donné qu'il à fermé ses portes...
    bref du coup me voilà en train de vous ennuyer vous !!
    Je ne comprends pas pourquoi en ligne 14 on doit utiliser le passage par référence... est-ce à cause du mot const de cette fonction get?
    En fait j'aimerais être bien sûr d'avoir compris...

    voici l'exercice qui me pose problème :

    ennoncé :

    Le but de cet exercice est d'écrire une classe représentant la notion de cercle.
    Écrivez un programme Cercle.cc dans lequel vous définissez une classe Cercle ayant comme attributs un rayon et les coordonnées du centre (du cercle).
    Déclarez ensuite les méthodes «get» et «set» correspondantes, par exemple :
    void getCentre(double& x, double& y) const { ... }
    void setCentre(double x, double y) { ... }
    ...
    NOTE : ceci n'est qu'un exemple parmi d'autres. Si vous préférez d'autres prototypes pour ces méthodes, libre à vous d'implémenter votre solution.
    Vous pourrez en particulier réviser votre programme après avoir fait les exercices 3 et 4.
    Ajoutez ensuite les méthodes (faisant partie de l'interface) :
    double surface() const qui calcule et retourne la surface du cercle (pi fois le carré du rayon);
    bool estInterieur(double x, double y) const qui teste si le point de coordonnées (x,y) passé en paramètre fait ou non partie du cercle (frontière comprise : disque fermé).
    La méthode retournera true si le test est positif, et false dans le cas contraire.
    Dans le main(), instanciez deux objets de la classe Cercle, affectez des valeurs de votre choix à leur attributs et testez vos méthodes surface et estInterieur.
    Remarque : la constante pi est souvent définie comme M_PI dans le module cmath (#include <cmath> au début de votre programme).
    Si ce n'est pas le cas pour votre compilateur, ajoutez simplement les lignes suivantes en début de votre programme, après les #include et le using namespace std; :
    #ifndef M_PI
    #define M_PI 3.14159265358979323846
    #endif

    solution proposée :
    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
     
    #include <iostream>
    #include <cmath>    // pour M_PI et sqrt()
     
    using namespace std;
     
    class Cercle {
    public:
        double surface() const { return M_PI * rayon * rayon; }
        bool estInterieur(double x1, double y1) const {
            return (((x1-x) * (x1-x) + (y1-y) * (y1-y))
                    <= rayon * rayon);
        }
        void getCentre(double& x_out, double& y_out) const {
            x_out = x;
            y_out = y;
        }
        void setCentre(double x_in, double y_in) {
           x = x_in;
           y = y_in;
        }
        double getRayon() const { return rayon; }
        void setRayon(double r) {
           if (r < 0.0) r = 0.0;
           rayon = r;
        }
    private:
        double rayon;
        double x;  // abscisse du centre
        double y;  // ordonnée du centre
    };
     
    int main () {
        Cercle c1, c2;
     
        c1.setCentre(1.0, 2.0);
        c1.setRayon(sqrt(5.0)); // passe par (0, 0)
        c2.setCentre(-2.0, 1.0);
        c2.setRayon(2.25);  // 2.25 > sqrt(5) => inclus le point (0, 0)
     
        cout << "Surface de C1 : " << c1.surface() << endl;
        cout << "Surface de C2 : " << c2.surface() << endl;
     
        cout << "position du point (0, 0) : ";
        if (c1.estInterieur(0.0, 0.0)) cout << "dans";
        else                           cout << "hors de";
        cout << " C1 et ";
        if (c2.estInterieur(0.0, 0.0)) cout << "dans";
        else                           cout << "hors de";
        cout << " C2." << endl;
     
        return 0;
    }

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 069
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 069
    Points : 12 113
    Points
    12 113
    Par défaut
    Ça sent le MOOC d'OCR, non ?
    Car l'exemple est particulièrement mal choisi avec une conception qui heurte tout conception orienté objet.
    Les méthodes "get" (les getter/accesseurs) et "set" (les setter/mutateur) sont des cochonneries venant du crétacées du JAVA et que les personnes d'OCR continue de coller partout.

    Donc, pour revenir à votre sujet du passage de paramètre en "double& x" versus "double x" :
    Quand il n'y a pas d'esperluette (&), il s'agit d'un passage par copie.
    C'est donc une copie de la variable qui à été donnée en paramètre de la fonction qui est passée à cette fonction dans ce cas.
    Vous modifierez donc la valeur de la copie et non la variable qui a été passé en paramètre.
    Toutes les modifications sur cette variable/copie seront donc automatiquement perdus dés la sortie de la méthodes car elle est automatiquement détruite à la fin de la méthode.

    Le passage par référence (avec l'esperluette) quand à lui, fait un pont/alias entre la variables données en argument et le paramètre de la méthode.
    Si vous modifiez les valeurs dans le paramètre passé en référence, la variable en argument sera aussi modifiée (vu qu'en mémoire l'argument et le paramètre seront confondu).

    Si vous vous posez la question, oui, le passage par référence est bien plus fréquent que le passage par copie.
    Pour être obliger d'utiliser des trucs en plus pour les cas les plus fréquents ? C'est malheureusement un des héritages du C sur le C++.

    Le const en fin de signature des accesseurs, c'est pour indiquer au compilateur que cette méthode de modifiera pas l'objet (ici le cercle).
    Cela peut-être très intéressant dans l'utilisation d'autres fonctionnalités du langage, comme la surcharge.

  3. #3
    Candidat au Club
    Homme Profil pro
    autodidacte en furie
    Inscrit en
    Août 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : autodidacte en furie

    Informations forums :
    Inscription : Août 2015
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par bacelar Voir le message
    Ça sent le MOOC d'OCR, non ?
    Car l'exemple est particulièrement mal choisi avec une conception qui heurte tout conception orienté objet.
    Les méthodes "get" (les getter/accesseurs) et "set" (les setter/mutateur) sont des cochonneries venant du crétacées du JAVA et que les personnes d'OCR continue de coller partout.
    en fait non, c'est un mooc de l'école polytechnique de Lausane. Je précise que c'est le tout premier exercice du mooc, et qu'ils ont une habitude pédagogique assez troublante : quand ils présentent une notion, il ne vont pas vers l'optimisation tout de suite, ils expliquent même parfois que tel solution n'est pas optimale et/ou opsolète.

    en tout cas je vous remercie pour votre réponse très claire.

    par contre vous semblez dire que les getter et setter ne sont plus de "bonnes pratiques", que doit on privilégier , une gestion des acces aux attributs et méthodes uniquement via l'utilisation des mots clés Public et Private ?

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 069
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 069
    Points : 12 113
    Points
    12 113
    Par défaut
    une gestion des acces aux attributs et méthodes uniquement via l'utilisation des mots clés Public et Private ?
    La question ne se pose pas en ces termes.
    Un objet n'est pas un regroupement de champs avec des méthodes qui sont là pour les manipuler, ça c'est la conception objet d'il y a plus de 30 ans (le début du C++).
    Un objet doit être pensé comme un fournisseur de service.
    Une classe comme Point2D peut avoir une sémantique de stockage d'une pair (x,y), mais c'est le genre de classe assez peu rependu, les classes valeurs, en opposition aux classes entités.
    Dans les classes de "stockage", l'utilisation de getter/setter n'apport strictement rien, autant mettre les champs de la classe en public et roule ma poule.

    Dans le cas plus commun de classe offrant des services, à aucun moment il devrait être nécessaire de savoir quel champ sont nécessaires à l'implémentation des services. Cela permettra de changer la manière d'implémenter les services sans à avoir à changer le code utilisateur de la classe. Donc, ici aussi les getter/setter ne sont pas utiles.

    Cas concret : Si vous voulez que les coordonnées internes de votre classe Cercle soient des coordonnées polaires et non cartésienne, pour des motifs d'optimisation potentielle sur une architecture spécifique, comment faire avec vos getter et vos setters qui font l'assertion de coordonnées cartésiennes et qui force le code utilisateur à utiliser la même assertion ?
    En fournissant une classe Cercle avec une API qui support les 2 types de coordonnées, vous verrez que le code utilisateur pourra passer d'une architecture à une autre sans difficultés.

  5. #5
    Candidat au Club
    Homme Profil pro
    autodidacte en furie
    Inscrit en
    Août 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : autodidacte en furie

    Informations forums :
    Inscription : Août 2015
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    merci pour la réponse que je vais potasser. (j'en ai besoin )

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Citation Envoyé par bacelar Voir le message
    Dans les classes de "stockage", l'utilisation de getter/setter n'apport strictement rien, autant mettre les champs de la classe en public et roule ma poule.
    Ça, ce n'est pas tout-à-fait vrai, une classe de stockage peut incorporer sa logique de validation.
    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.

  7. #7
    Candidat au Club
    Homme Profil pro
    autodidacte en furie
    Inscrit en
    Août 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : autodidacte en furie

    Informations forums :
    Inscription : Août 2015
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Ça, ce n'est pas tout-à-fait vrai, une classe de stockage peut incorporer sa logique de validation.
    bonjour !

    dans mon exemple, avec une classe aussi "basique" que la mienne, getteur et setteur ont un utilité selon vous? parceque bon... mon code marche quand même très bien sans, en utilisant public comme l'avait suggéré bacelar.

    par ailleur, "validation de données", est-ce bien : vérifier que les données sont valides pour l'objet? par exemple, vérifier que la longueur d'un rectangle est supérieure à 0 ?

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 518
    Points
    41 518
    Par défaut
    C'est comme ça que je l'entends, en tout cas.
    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.

  9. #9
    Candidat au Club
    Homme Profil pro
    autodidacte en furie
    Inscrit en
    Août 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : autodidacte en furie

    Informations forums :
    Inscription : Août 2015
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    merci , quand on débute certains termes ne sont pas evident ^^

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    Citation Envoyé par Médinoc Voir le message
    Ça, ce n'est pas tout-à-fait vrai, une classe de stockage peut incorporer sa logique de validation.
    Oui, mais les classes qui ne s'occupent que du stockage ont, typiquement, sémantique de valeur et sont, par nature (ou, du moins, devraient être par nature) immuables / constantes car m'enfin, si tu as une coordonnée 4,3; et que tu change une seule de ces deux valeurs, tu obtiens bel et bien une coordonnée différente

    Alors, je sais... il est parfois plus "pratique" de permettre la mutabilité de ce genre de classe... Mais bon, quand même

    EDIT : en plus, là, on parle quand même d'un cercle, qui est typiquement une classe qui a sémantique d'entité... Les fonctions qu'il expose devraient donc veiller à n'exposer que des services que l'on est en droit d'attendre de la part du cercle (move / moveTo et autres joyeusetés du genre )
    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

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    Oui, mais les classes qui ne s'occupent que du stockage ont, typiquement, sémantique de valeur et sont, par nature (ou, du moins, devraient être par nature) immuables / constantes car m'enfin, si tu as une coordonnée 4,3; et que tu change une seule de ces deux valeurs, tu obtiens bel et bien une coordonnée différente

    Alors, je sais... il est parfois plus "pratique" de permettre la mutabilité de ce genre de classe... Mais bon, quand même
    Le problème est qu'en C++ (contrairement au C#) les classes de stockage à sémantique de valeur ne peuvent pas être écrasées si on déclare leurs membres constants, donc leur immuabilité ne peut être que dans leur interface (pas de modifieurs publics). C'est... dommage.
    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.

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

Discussions similaires

  1. Passage par référence
    Par e1lauren dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 01/09/2006, 12h59
  2. Passage par copie vs passage par référence
    Par bolhrak dans le forum C++
    Réponses: 11
    Dernier message: 20/08/2006, 23h37
  3. Réponses: 4
    Dernier message: 26/12/2005, 17h01
  4. Passage par référence
    Par difficiledetrouver1pseudo dans le forum Langage
    Réponses: 9
    Dernier message: 28/09/2005, 11h17
  5. Problème très rapide de passage par référence
    Par Noxexplorer dans le forum ASP
    Réponses: 2
    Dernier message: 23/06/2005, 10h02

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