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 :

Classes imbriquées : accès méthode objet fils


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 42
    Points : 38
    Points
    38
    Par défaut Classes imbriquées : accès méthode objet fils
    Bonsoir,

    Je viens de commencer le CPP, la POO et j'ai un problème de compréhension.
    Pour comprendre, j'ai créé un exemple simple.

    J'ai créé une classe "Vehicule" et une classe "Roue".

    La classe Roue contient la pression des pneus. J'ai une méthode qui modifie la pression.
    Quand je créé dans le main un objet roue indépendant, tout fonctionne parfaitement.

    Un des attributs de la classe Vehicule est une Roue (de la classe Roue).
    La création se passe bien, j'arrive à faire afficher la pression de création de la roue de l'objet véhicule, la modification de la pression de la roue de l'objet véhicule semble fonctionner, mais l'affichage donne la valeur initiale, pas la valeur modifiée.

    Mon explication n'est pas très claire : ci joint les fichiers (C::Block).

    Cela fonctionne, à condition que je créé dans le fichier Vehicule, une méthode qui accède à la méthode de Roue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void Vehicule::changerPressionLiee(float variation) {
        m_roue.changePression(variation);
    }
    Cela ne me parait pas rationnel de devoir recréer toutes les méthodes de Roue dans Vehicule : je suppose qu'on peut y accéder directement.
    Peut être par le biais de pointeurs : j'ai essayé, en vain.

    Merci pour éclairage... Et je reste disponible pour toutes précisions complémentaires.

    vehicule.cpp
    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
    #include <string>
    #include "Vehicule.h"
     
    using namespace std;
     
    Vehicule::Vehicule() : m_marque("Peugeot"), m_roue() {
     }
    string Vehicule::get_marque() const {
        return m_marque;
    }
    Roue Vehicule::get_roue() {
        return m_roue;
    }
    void Vehicule::changerPressionLiee(float variation) {
        m_roue.changePression(variation);
    }
    Fichiers attachés Fichiers attachés

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 42
    Points : 38
    Points
    38
    Par défaut
    Re-bonsoir,

    Je me réponds à moi-même : je tournais autour des pointeurs sans y arriver mais j'ai une solution qui fonctionne.

    Dans ma classe Vehicule, j'ai supprimé get_roue (qui était sensé renvoyer l'objet Roue) et remplacé par un pointeur vers la Roue du Vehicule :

    En public: dans le .h de vehicule, je déclare le pointeur
    Dans le .cpp de Vehicule, je lui donne l'adresse de ma variable Roue (cela reste un getteur mais qui renvoie un pointeur et non l'objet) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Roue *Vehicule::pointeurRoue() {
        return &m_roue;
    }
    Dans le main, je l'utilise ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    monVehicule.pointeurRoue()->changePression(2);
        cout << "Pression changee : " << monVehicule.pointeurRoue()->get_pression() << endl;

    Cela fonctionne, mais je ne sais pas si c'est ce qu'il y a de mieux.

    A priori, je n'ai pas de delete du pointeur à faire car je n'utilise pas une allocation dynamique par New.

    J'ai essayé une variable pointeurRoue initialisée dans le constructeur, mais ça ne fonctionne pas, la pression est incohérente : il semble que le pointeur ne pointe pas sur la bonne adresse (dans le constructeur, la Roue n'est pas encore initialisée ?)
    Dans vehicule.h, en public:
    Dans vehicule.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Vehicule::Vehicule() : m_marque("Peugeot"), m_roue() {
        Roue *pRoue = &m_roue;
     }
    Bonsoir.
    Fichiers attachés Fichiers attachés

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Je ne vais pas ouvrir les fichiers joints (tu peux mettre le code incriminé directement pour qu'on gagne du temps), mais est-ce que tu ne retournerais pas la roue par copie et non par référence ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Gné ? Les variables membres sont initialisées dans la liste d'initialisation donc oui elle existe et est tout à fait valide dans le corps du constructeur.
    Et cette variable n'est jamais qu'un offset depuis this dont l'adresse est valide dès que l'objet est construit donc.
    Quelque soit ton problème, il n'est pas là et ajouter un pointeur pour le corriger est franchement moyen.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 42
    Points : 38
    Points
    38
    Par défaut
    Bonjour, et merci Bousk de m'avoir relancé...

    Effectivement, je revu mon code et ça fonctionne : l'objet est bien créé avant d'entrer dans le constructeur (je ne sais plus ce que j'avais fait)

    Le main()
    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
    #include <iostream>
    #include "Vehicule.h" //Pas besoin d'inclure Roue.h
     
    using namespace std;
     
    int main()
    {
        Vehicule monVehicule;
        cout << "Marque du vehicule : " << monVehicule.get_marque() << endl;
     
        cout << "Pression initiale : " << monVehicule.pointeurRoue->get_pression() << endl;
        monVehicule.pointeurRoue->changePression(0.5);
        cout << "Pression changee : " << monVehicule.pointeurRoue->get_pression() << endl;
     
        return 0;
    }
    Vehicule.h
    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
    #ifndef VEHICULE_H_INCLUDED
    #define VEHICULE_H_INCLUDED
    #include <string>
    #include "Roue.h"
     
    class Vehicule {
     
        public:
        Vehicule();
        std::string get_marque() const;
        Roue *pointeurRoue; //Déclarer le pointeur vers l'objet roue
     
        private:
        std::string m_marque;
        Roue m_roue; //Le véhicule a une marque + une roue
    };
     
    #endif // VEHICULE_H_INCLUDED
    Vehicule.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <string>
    #include "Vehicule.h"
     
    using namespace std;
     
    Vehicule::Vehicule() : m_marque("Peugeot"), m_roue() {
        pointeurRoue=&m_roue; //Affecter l'adresse de la roue
     }
    string Vehicule::get_marque() const {
        return m_marque;
    }
    Roue.h
    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
    #ifndef ROUE_H_INCLUDED
    #define ROUE_H_INCLUDED
     
    class Roue {
     
        public:
        Roue();
        float get_pression() const;
        void changePression(float variation);
     
        private:
        float m_pression;
     
    };
     
    #endif // ROUE_H_INCLUDED
    Roue.cpp
    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
    #include <iostream>
    #include "Roue.h"
     
    using namespace std;
     
    Roue::Roue() : m_pression(2.2) {
    }
    float Roue::get_pression() const {
        return m_pression;
    }
    void Roue::changePression(float variation) {
        cout << "=> modification pression : " << m_pression << " + " << variation << " = ";
        m_pression += variation;
        cout << m_pression << endl;
    }
    Par contre, je suis obligé de mettre la variable pointeurRoue en public pour y accéder, ce qui n'est pas top.
    => Il vaut sans doute mieux passer par un getter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Roue  *Vehicule::get_pointeurRoue()  {
        return &m_roue;
    }
    Merci pour tes remarques mais je ne comprends pas "ajouter un pointeur pour le corriger est franchement moyen."
    - Je ne le corrige pas, je l'ai initialisé dans "vehicule.h" et affecté dans le constructeur de vehicule.
    Si tu peux m'en dire un peu plus...

    Merci et bonne journée

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Il faudrait (re)lire ton bouquin section référence.
    https://cpp.developpez.com/faq/cpp/?...-une-reference
    https://cpp.developpez.com/faq/cpp/?...-des-pointeurs
    https://cpp.developpez.com/faq/cpp/?...d-une-fonction

    Et donc j'avais raison depuis le début : tu retournes ta variable par copie alors qu'il faut retourner une référence.
    Mettre un pointeur public comme ça est vraiment mauvais. Soit roue est un détail d'implémentation et est interne et privée, soit elle est publique.
    Soit la voiture a toujours une roue qu'on peut mettre à jour, soit on peut lui passer des roues et les changer à tout moment.

    Voilà ce que devrait être Vehicule, en enlevant tout ce qui est inutile.
    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
    #pragma once
    #include "Roue.h"
     
    class Vehicule
    {
    public:
        Vehicule() = default;
        Vehicule(const std::string& marque) : m_marque(marque) {}
        const std::string& get_marque() const { return m_marque; }
        Roue& get_roue() { return m_roue; }
        const Roue& get_roue() const { return m_roue; }
     
    private:
        std::string m_marque{"Peugeot"};
        Roue m_roue; //Le véhicule a une marque + une roue
    };
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

Discussions similaires

  1. Méthodes et classes imbriquées
    Par chagala dans le forum Débuter avec Java
    Réponses: 7
    Dernier message: 27/10/2009, 18h13
  2. Accès aux objets d'une classe créés dynamiquement
    Par mulfycrowh dans le forum Débuter
    Réponses: 5
    Dernier message: 17/10/2009, 23h03
  3. Réponses: 5
    Dernier message: 25/07/2007, 15h34
  4. Réponses: 5
    Dernier message: 01/02/2007, 13h14
  5. [c#] Méthode d'accès aux objets de ma form1
    Par SDuh dans le forum Windows Forms
    Réponses: 5
    Dernier message: 21/03/2006, 11h21

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