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

Langage C++ Discussion :

Question sur la POO (héritages)


Sujet :

Langage C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 133
    Points : 122
    Points
    122
    Par défaut Question sur la POO (héritages)
    Bonjour à tous !

    Une question me taraude, je ne sais si la réponse est évidente ou non, mais visiblement, je ne la trouve pas. Je m'en remets à vous alors...!

    Ma question est la suivante :

    Imaginons trois classes et un cpp :

    Une classe VÉHICULE,
    une classe VOITURE héritée de VÉHICULE,
    une classe CAMION héritée de VÉHICULE,

    dans mon cpp, je souhaite que l'utilisateur puisse consulter son garage, soit les VÉHICULE à sa disposition, contenues dans un vecteur.

    Puis-je construire des objets VOITURE et/ou CAMION, les charger dans mon vecteur de type VÉHICULE, et ensuite accéder aux méthodes contenues dans ces classes ?

    Ou suis-je obligé créer deux vecteurs, de type VOITURE et CAMION, pour afficher l'ensemble des VÉHICULE de l'utilisateur et accéder aux méthodes ?


    Merci d'avance pour vos précieuses informations !

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2009
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2009
    Messages : 215
    Points : 558
    Points
    558
    Par défaut
    Un des principes de l'héritage est que justement, quand un objet de type parent est accepté, un objet de type enfant le soit aussi.

    Tu peux donc sans problèmes placer tes voitures et camions dans le tableau de véhicules, puis faire appel aux méthodes qu'ils ont héritées ou surchargées de la classe véhicule.

    Il n'y a que si tu veux faire appel à leurs méthodes spécifiques que tu devras les reconvertir explicitement (cast) dans leur type.

  3. #3
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Ta question est tout à fait normale, ne t'inquiètes pas.

    Quand tu définis une classe Véhicule qui est destinée, non pas à être instanciée en tant que telle, mais à être dérivée par des classes comme Voiture et Camion, ta classe Véhicule reste quand même un point clé. En effet, toutes les fonctions que tu déclareras virtuelles dans Véhicule seront les seules que tu pourras appeler sans te soucier qu'il s'agisse d'un Camion ou d'une Voiture lorsque tu traverseras ton tableau de Vehicule. Justement, cela va te paraître logique car si tu veux traiter 1000 Véhicules de manière uniforme, il te faut les fonctions permettant ces traitements dans la classe Véhicule, et il faut qu'elles soient virtuelles. Elles peuvent même être virtuelles pures, le tout étant que chaque classe qui dérive de Véhicule redéfinisse le comportement qui correspond à cette classe.

    Petit exemple ici :
    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
     
    class Vehicule
    {
      public:
      virtual ~Vehicule() { }
      virtual void roule() = 0;
    };
     
    class Voiture : public Vehicule
    {
      public:
      void roule() { std::cout << "Je suis une voiture et je roule" << std::endl; }
      void transporter_famille(const Famille& f) { /* ... */ }
    };
     
    class Camion : public Vehicule
    {
      public:
      void roule() { std::cout << "Je suis un camion et je roule" << std::endl; }
      void transporter_marchandise(const Marchandise& m) {*/* ... */ }
    };
     
    std::vector<Vehicule*> v;
    v.push_back(new Camion);
    v.push_back(new Voiture);
    v.push_back(new Voiture);
     
    for(int i = 0 ; i < v.size(); i++)
    {
      v[i]->roule();
      // v[i]->transporter_marchandise(Marchandise()); ne compilerait pas car
      // transporter_marchandise ne fait pas partie de l'interface de Vehicule,
      // qui est l'interface qui nous permet de manipuler indifféremment
      // des Camion ou des Voiture.
    }
     
    // il faut effacer proprement les pointeurs ici
     
    Camion c;
    c.transporter_marchandise(Marchandise()); 
    // marche car on passe cette fois directement par Camion, sans vouloir
    // traiter indifféremment un Camion ou une Voiture.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    Je me permets d'apporter deux petits compléments à l'explication déjà claire des précédents intervenants et en particulier au code de Alp :
    1/ Pour les fonctions virtuelles, on préfère utiliser l'idiome NVI afin d'accroître la modularité des interfaces :
    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
    class Vehicule
    {
      public:
      virtual ~Vehicule() { }
      void roule()
      {
       faire_roule();
      }
      private:
      virtual void faire_roule();
    };
     
    class Voiture : public Vehicule
    {
      public:
      void transporter_famille(const Famille& f) { /* ... */ }
      private:
      void faire_roule() { std::cout << "Je suis une voiture et je roule" << std::endl; }
    };
     
    class Camion : public Vehicule
    {
      public:
      void transporter_marchandise(const Marchandise& m) {*/* ... */ }
      private:
      void faire_roule() { std::cout << "Je suis un camion et je roule" << std::endl; }
     
    };
    2/ Il est conseillé d'encapsuler ton pointeur brut présent dans vecteur par un pointeur intelligent (cf le tutoriel sur les pointeurs intelligents de Loic Joly).

  5. #5
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Un oubli :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Voiture : public Vehicule
    {
        //...
    };
     
    class Camion : public Vehicule
    {
       //...
    };

  6. #6
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Effectivement, j'ai modifié le code, merci

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Citation Envoyé par 3DArchi Voir le message
    1/ Pour les fonctions virtuelles, on préfère utiliser l'idiome NVI afin d'accroître la modularité des interfaces.
    Oui enfin... C'est un courant de pensée comme un autre, de là à dire "on préfère" c'est vite dit.

    MAT.

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

    Informations professionnelles :
    Activité : aucun

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

    Il n'y a qu'un détail qui n'a pas été abordé dans les autres réponses:

    Tu peux effectivement créer un tableaux de pointeurs (de préférence intelligents) de type Vehicule pour représenter la flotte à disposition du garage, mais tu ne pourra manipuler ces véhicules... qu'au travers de l'interface publique... de Vehicule

    C'est à dire que, si tu viens à un moment donné à vouloir manipuler l'un des véhicules en tant que camion ou en tant que voiture (parce qu'il peut y avoir des comportements qui n'apparaissent que pour les camions ou que pour les voitures), il faudra trouver le moyen de t'assurer que tu manipule bien... un camion ou une voiture.

    Mais tant que tu te "cantonnera" à considérer tes voitures et tes camions comme des véhicules, les réponses précédentes sont tout ce qu'il y a de plus juste

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 133
    Points : 122
    Points
    122
    Par défaut
    Tout d'abord merci de vos nombreuses réponses, rapides et intéressantes !
    Je vais potasser l'idée des fonctions virtuelles, je ne connaissais vraiment pas.

    "C'est à dire que, si tu viens à un moment donné à vouloir manipuler l'un des véhicules en tant que camion ou en tant que voiture (parce qu'il peut y avoir des comportements qui n'apparaissent que pour les camions ou que pour les voitures), il faudra trouver le moyen de t'assurer que tu manipule bien... un camion ou une voiture."

    -> c'était l'idée en réalité. Il faudrait un genre de fonction TypeOf(Véhicule) certainement alors.
    En fait je voulais faire un truc du genre

    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
     
    class Véhicule
    {
    protected : 
    string marque;
    etc...
    }
     
    class Voiture : Véhicule
    {
    public :
    void faireLeCapitaineDeSoiree() {
    // code
    }
     
    class Camion : Véhicule
    {
    void attacherUneRemorque() {
    // code
    }
     
    // Puis dans le cpp
     
    main() {
    std::vector<Véhicule> MesVéhicules; //Collection remplie de Camion et Voiture
    for (int i = 0; i < MesVéhicules.size(); i++) {
    std::cout << i << MesVéhicules[i].getMarque() << std::endl;
     
    /* c'est à ce moment précis que je sèche :
    il faudrait arriver à connaître le type réel de MesVéhicules[i], et savoir si on pourrait faire MesVéhicules[i].attacherUneRemorque() par exemple.
    La première réponse suggérait un cast, j'essayerai ce soir.
    Merci beaucoup en tous cas encore, votre aide m'est précieuse !
    */
    }

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Ashura95 Voir le message
    -> c'était l'idée en réalité. Il faudrait un genre de fonction TypeOf(Véhicule) certainement alors.
    En général, c'est là où la conception devient délicate. Parce que soit tu manipules des 'Véhicule' et seule l'interface de Véhicule t'intéresse, soit tu es intéressé par l'interface de Voiture, alors tu devrais manipuler des Voiture et pas avoir à downcaster un Véhicule.
    Par exemple :
    Un objet Garage manipule des 'Véhicule' et utilise l'interface 'Vidanger'. Peu lui importe de savoir si c'est un camion ou une voiture (modulo la quantité d'huile ).
    En revanche, un objet 'ConducteurParticulier' manipule des 'Voiture' là où un 'Camionneur' manipule des 'Camion'.

    En général, ça va de pair avec qui possède l'objet et qui n'en n'a qu'une référence/pointeur. Ici, 'ConducteurParticulier' possède l'objet et sait parfaitement ce que c'est. 'Garage' n'aurait alors qu'une référence/pointeur vers cet objet le temps de la réparation, et n'en connait que son aspect 'Véhicule'.

Discussions similaires

  1. questions sur la POO : new et this
    Par Invité dans le forum Débuter
    Réponses: 23
    Dernier message: 06/11/2010, 01h56
  2. Question sur la POO
    Par Nicocanta dans le forum wxWidgets
    Réponses: 0
    Dernier message: 09/02/2010, 13h06
  3. [POO] Questions sur la POO
    Par Jeakr dans le forum Langage
    Réponses: 1
    Dernier message: 26/09/2008, 16h59
  4. Question sur la POO
    Par QAYS dans le forum Langage
    Réponses: 2
    Dernier message: 18/10/2007, 16h06

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