Partage
  • Partager sur Facebook
  • Partager sur Twitter

Héritage pas bien compris

J'ai un exemple

    2 juillet 2007 à 8:57:22

    Salut, Ca fait 2 ou 3 jours que je n'arrive pas à assimiler un point : l'héritage.

    class Emplacement
    {
    protected:
        int x, y;              // Données ne pouvant être accédées
                               // que par les classes filles.

    public:
        void Change(int, int); // Méthode toujours accessible.
    };

    void Emplacement::Change(int i, int j)
    {
        x = i;
        y = j;
        return;
    }

    class Point : public Emplacement
    {
    protected:
        unsigned int couleur;  // Donnée accessible
                               // aux classes filles.

    public:
        void SetColor(unsigned int);
    };

    void Point::SetColor(unsigned int NewColor)
    {
        couleur = NewColor;    // Définit la couleur.
        return;
    }

    (tiré de casteyde.christian.free.fr)

    Ma question : A quoi sert l'héritage dans ce code et pourquoi l'utilise-t-on.
    • Partager sur Facebook
    • Partager sur Twitter
      2 juillet 2007 à 9:33:06

      Tu pourras faire ça, par exemple :

      Emplacement emplacement;
      Point point;

      emplacement.Change(10, 15);
      point.Change(20, 35)); // avec l'héritage, Point a hérité de la méthode Change, donc il peut l'appeler
       
      • Partager sur Facebook
      • Partager sur Twitter
        2 juillet 2007 à 9:40:52

        Ah, d'accord. C'est tout bête en fait ou il y a des petites ambiguités?

        EDIT : Est-ce que ça marche avec les opérateurs?
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          2 juillet 2007 à 9:55:08

          Oui , mais il faut mieux en redéfinir certain.
          Comme l'operateur d'affectation s'il a été redéfinit dans la classe parente.

          Edit : l'héritage ne permet quie la réutilisation de l'existant , ca permet aussi de faire des chosess très puissante comme le polymorphisme avec les fonctions virtuelles.
          • Partager sur Facebook
          • Partager sur Twitter
            2 juillet 2007 à 15:42:45

            L'héritage sert a l'acces de membres protégés par les classe filles. Certains disent que l'héritage n'est pas utile ( ces gens se débrouillent pour que les variables soient accessibles quand il faut sans les mettre en porté globale ), alors que d'autres affirment leur indispensabilité... A toi de voir :)
            • Partager sur Facebook
            • Partager sur Twitter
              2 juillet 2007 à 16:04:18

              Salut,

              Si je peux me permettre (bien que pas spécialiste du tout en conception objet), le problème avec l'héritage n'est pas tant qu'il soit utile ou inutile, mais surtout qu'on a facilement tendance à voir dans l'héritage la solution miracle à tous les problèmes de conception, alors que ce n'est pas toujours la meilleure solution (et d'aucuns diront même que c'est la pire, mais ça n'engage qu'eux).

              Toujours est-il que tous les bouquins que j'ai jamais consulté sur la conception et la modélisation objet posent comme premier principe ou presque, "préférez la composition à l'héritage".

              Après, comme dit ironzorg, à toi de voir. :)
              • Partager sur Facebook
              • Partager sur Twitter
                2 juillet 2007 à 17:13:29

                En règle générale, on utilise l'héritage que dans un seul cas:

                pour représenter la relation "est un"

                Si tu as une classe représentant des animaux.

                Alors la classe chien hérite de animaux, car chien EST UN animal

                La classe voiture par contre n'héritera pas de animal, car voiture n'est pas un animal.


                Si tu ne peux pas utiliser la relation EST UN, alors c'est que l'héritage n'est pas adapté à ce que tu veux faire.
                (Dans la plupart des cas).
                • Partager sur Facebook
                • Partager sur Twitter
                Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                  2 juillet 2007 à 21:04:31

                  Faut préciser "EST UN" au sens de la théorie des ensembles (quelques exceptions cependant).

                  Parce qu'on peut aussi mal formuler ses phrases en disant : un chient, c'est une tête, des poils, des pattes, etc...

                  Attention aussi aux abus, les exemples-bateau : au sens de la POO un carré n'est en général pas un rectangle...

                  Voir le LSP (Liskov Substitution Principle) sur Google.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 juillet 2007 à 23:26:29

                    On peut distinguer deux formes d'héritage :
                    - une de réutilisation : pour importer du code (qui est en concurrence avec la composition) (cf les notions de "utilise un" / "est implémenté en termes de" / ...)
                    - une de substitution : pour "être utilisé en place de" (qui n'a pas de concurrent direct, et est vraiment propre au monde OO) (cf la notion de "est-un", le LSP, etc.)
                    - et les formes hybrides...

                    Le C++ permet de dintinguer assez proprement ("fortement" serait plus juste ; je trouve ruby plus propre) les deux premières formes d'héritage. Le premier sera privé, le second public. D'autres langages ne le peuvent pas. D'où la sacro-sainte règle de préférer la composition -- on ne peut pas faire autrement avec ces langages soit disant plus OO (non, non ce n'est pas un coup bas. Quoique. :-° )
                    Par extension, vu que syntaxiquement l'héritage public permet une subtitution, on fait en sorte qu'il ne soit pas utilisé pour des héritages où la substition n'est pas désirée/possible/...

                    Quoi d'autre?
                    Oui. Bof bof cet exemple. C'est un cas limite hybride. Il est des visions où il serait acceptable de dire qu'un point coloré est-un point. Et d'autres dans lesquelles c'est une parfaite hérésie. Manipule tes points comme des entités vivant leur vie propre, c'est OK. Manipules tes points comme des valeurs que tu peux additionner, affecter, etc. et tu es mort.

                    Et oui, les opérateurs sont très difficilement compatibles avec l'héritage public de substitution. Pareil vous vous dites : "mais dans les autres langages je n'ai pas ces problèmes?!". Et oui! Dans ces autres langages, on ne peut pas donner une sémantique de valeur (voire "mathématique") à nos types. (<analogie à 2 balles>De même que l'on ne va pas se marcher sur les lacets quand on a des velcros..</>)

                    EDIT: s/utile/utilise/
                    • Partager sur Facebook
                    • Partager sur Twitter
                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                      3 juillet 2007 à 10:01:04

                      Le mieux pour les opérateurs, est de les redéfinir dans la classe fille, car on a de gros problème sinon. Mais il est assez rare de dériver une classe avec des opérateurs (d'après mon expérience personnelle, ce qui ne veut rien dire en gros)
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                        3 juillet 2007 à 10:39:31

                        point hérite de toutes les méthodes d' Emplacement c'est à dire que dans ton code, c'est "comme si la classe point contenait toutes les méthodes de Emplacemet"seulement comme Emplacement contient des méthode de placement tu peux réutiliser ton code pour un autre projet sans avoir les méthodes de la classe point.

                        L'héritage te permet d'éviter sa quand tu te trouve dans ta classe point:

                        Emplacement Empl;
                        Empl.placer(x,y);
                         


                        Tu peux directement faire sa:

                        placer(x,y);//la méthode placer se trouve toujours dans Emplacement
                         



                        Voilà j'espère avoir été assez clair mais trouve un bon schéma de classe pour mieux comprendre :)

                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 juillet 2007 à 19:27:23

                          Citation : no@r

                          point hérite de toutes les méthodes d' Emplacement c'est à dire que dans ton code, c'est "comme si la classe point contenait toutes les méthodes de Emplacemet"seulement comme Emplacement contient des méthode de placement tu peux réutiliser ton code pour un autre projet sans avoir les méthodes de la classe point.



                          En fait la classe Point contient les méthodes de Emplacement (elle ne fait pas semblant) ainsi que ses données membres.

                          voici un schéma représentant des instances en mémoire

                           un objet d'Emplacement
                          +-------------+
                          | Emplacement |
                          +-------------+

                          un objet de Point
                          +-------------+-------+
                          | Emplacement | Point |
                          +-------------+-------+


                          Citation : no@r

                          Les données définies dans la classe Point sont juxtaposées aux données de la classe Emplacement

                          L'héritage te permet d'éviter sa quand tu te trouve dans ta classe point:


                          Emplacement Empl;
                          Empl.placer(x,y);
                           



                          Tu peux directement faire sa:


                          placer(x,y);//la méthode placer se trouve toujours dans Emplacement
                           




                          Voilà j'espère avoir été assez clair mais trouve un bon schéma de classe pour mieux comprendre :)



                          Ce n'est pas vraiment clair...

                          oui on peut utiliser directement placer(); parce que placer fait parti de la classe ( Cela reviens au concept "Est un" ) alors que dans ton premier exemple je crois comprendre que la classe contient un objet de Emplacement (cela reviens au concept "A un" )

                          class Point
                          {
                             Emplacement m_Empl;
                             //...
                          }


                          Mais ce n'est pas que ça! Car grâce à l'héritage les méthodes publiques de Emplacement sont accessibles à l'extérieur de la classes pour les objets Emplacement et Point.

                          Voici un exemple à partir du code de base de gogeta1
                          J'ai ajouté un exemple des opérations de cast possible entre les classes mère et filles
                          int main()
                          {
                              int x = 10, y = 10;

                              Emplacement empl;
                              Point point;

                              empl.Change( x, y ); // ok!
                              point.Change( x, y ); // ok!

                              Emplacement * p_empl = 0;
                              Point * p_point = new Point;

                              p_empl = p_point; //ok! (les méthodes de Point ne seront pas accessibles) Down casting automatique

                              p_empl->Change( x, y ); // ok!

                              p_empl = new Point; //ok! ( déclaration d'un Point en mémoire, conservé par un pointeur de la classe de base : les méthodes de Point ne seront pas accessibles )

                              delete p_point;

                              p_point = static_cast<Point *>( p_empl ); // ok! Les méthodes de Point seront accessible par p_point (up casting déclaré, je spécifie que la zone mémoire est assez grande pour un Point)

                              p_point->SetColor( 100 ); // ok!

                              delete p_point;

                              return 0;
                          }
                          • Partager sur Facebook
                          • Partager sur Twitter
                            3 juillet 2007 à 21:45:14

                            Citation : Nanoc

                            Le mieux pour les opérateurs, est de les redéfinir dans la classe fille, car on a de gros problème sinon. Mais il est assez rare de dériver une classe avec des opérateurs (d'après mon expérience personnelle, ce qui ne veut rien dire en gros)


                            Il y a une excellente raison. C'est difficilement compatible.
                            Va écrire un opérateur + qui additionne un point avec un point coloré. Quel devra être le type de retour ? Comment faire quand des points colorés passent au travers de fonctions qui les voient comme des points (références constantes) et que l'on cherche à la additionner.

                            Même série de question pour les comparaisons.

                            PS: inutile de trop se prendre la tête, la seule bonne solution est : "mauvais design:, les hériarchies polymorphes sont incompatibles avec la sémantique de valeur, et ... en fait c'est logique"
                            • Partager sur Facebook
                            • Partager sur Twitter
                            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.

                            Héritage pas bien compris

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown