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 :

Sémantique de valeur et héritage


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Sémantique de valeur et héritage
    Hello,

    Bon, je remets sur le tapis un sujet récurrent, mais qui garde toujours quelques traces de nébulosités.

    Dans la FAQ, il est dit que cela a peu de sens d'avoir de l'héritage avec une sémantique de valeur (je ne vois d'ailleurs pas pourquoi la FAQ s'intéresse particulièrement aux fonctions virtuelles). Je ne comprend pas vraiment pourquoi.

    En l'occurrence, je travaille sur une classe qui représente un coût. Ce coût comprend différentes valeurs scalaires, de type différent, qui se complètent. J'ai une autre classe de coût qui ajoute des composantes scalaires, et qui hérite donc de la première classe.

    Pourquoi cela pose-t-il un problème ?

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Alors je ne me souviens plus vraiment de la démonstration.

    Les classes à sémantique d'entité doivent interdire la copie et l'affectation. En revanche, on peut implémenter une méthode clone() par exemple.

    Les classes à sémantique de valeurs doivent autoriser la copie et l'affectation.

    Or, si ont a une classe à sémantique de valeur avec un héritage (ex. Fille hérite de Mère), on peut avoir une fonction qui prenne en paramètre une Mère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void foo(Mere & mere)
    {
    }
    On pourra alors lui transmettre une Fille grâce au polymorphisme. Or si cette fonction foo se met à faire une copie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(Mere & mere)
    {
            Mere m = mere;
    }
    On va se retrouver avec un objet qui n'est pas une Fille, ainsi on risque d'avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Mere m = mere;
    m != mere;
    Sans compter que l'objet m peut très bien être dans un état "invalide" pour une instance de Mere.

    Ainsi il est très déconseillé d'utiliser l'héritage publique pour des classes à sémantique de valeur.

  3. #3
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Il y a deux soucis :
    - un sémantique -> Quel est le sens dans ton système à ajouter des couts qui ne sont pas du même type (ou même de les comparer, car c'est la même question) ? Il me semble que tu penses factorisation de code, et non pas LSP. Or un héritage (public) sans LSP, c'est un héritage bancal. Autant faire de la composition.
    P.ex., si je dois écrire Point + Vector, je ne vais pas dériver publiquement Point3D de Point2D pour écrire le bousin. A la place, je veux un meilleur typage qui ne me laissera pas faire des non-sens comme Point3D + Vector2D.

    - un technique -> le slicing rend très difficile l'écriture ICout operator+(ICout, ICout) (il faut passer par l'idiome enveloppe-lettre ou d'autres feintes dans le genre)

    Bref, de la lecture:
    - http://www.drdobbs.com/cpp/compariso...ance/240149250
    - http://www.drdobbs.com/cpp/if-c-obje...equa/240146950
    - http://www.angelikalanger.com/Articl...ls/Equals.html
    - http://www.developpez.net/forums/d13...n/#post7141642 (je m'étais emmêlé dans mes ensembles ^^')
    - http://akrzemi1.wordpress.com/2012/0...lue-semantics/
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Il y a deux soucis :
    - un sémantique -> Quel est le sens dans ton système à ajouter des couts qui ne sont pas du même type (ou même de les comparer, car c'est la même question) ? Il me semble que tu penses factorisation de code, et non pas LSP. Or un héritage (public) sans LSP, c'est un héritage bancal. Autant faire de la composition.
    P.ex., si je dois écrire Point + Vector, je ne vais pas dériver publiquement Point3D de Point2D pour écrire le bousin. A la place, je veux un meilleur typage qui ne me laissera pas faire des non-sens comme Point3D + Vector2D.

    [...]

    - http://www.angelikalanger.com/Articl...ls/Equals.html
    Ce qui est amusant, c'est que tu parles de LSP, issu du cerveau de Barbara Liskov, qui se sert justement d'une hérarchie Point2D/Point3D pour illustrer l'implémentation en Java de la méthode equals() (sémantique de valeur).
    Pour juste se faire dégommer par Angelika Langer qui dit que son implémentation est pourrie (non respect de la transitivité).

    Comme quoi, ce n'est pas si évident !

  5. #5
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Pour moi, un point3D n'est pas un point2D, et que si on utilise l'héritage pour rajouter des choses à un type, ça ne marche pas comme ça. Mais alors pas du tout! [Et malheureusement, c'était l'argument de vente de l'héritage des années 80-90 -> réutiliser du code... ]
    Là, l'exemple auquel tu fais référence vient du monde Java, et Java ne permet pas de proposer un héritage de réutilisation qui ne permet pas une substituabilité syntaxique -- note dans les conclusions le "ne pas hériter aurait été plus propre ici". De plus, le Java souffre, comme le C++, du non support des multi-méthodes.

    Et là, nous sommes à la croisée de tous ces problèmes à vouloir implémenter l'égalité sur des objets tirés de hiérarchies juste pour pouvoir factoriser du code source par héritage.
    Le problème en C++ ne se voit pas sur l'égalité, mais au moment de vouloir copier. Et les racines (sémantiques, j'ai envie de dire) du problème sont les mêmes, bien que les conséquences techniques soient différentes.
    Ce n'est pas une théorie, mais une intuition personnelle (comme quoi, c'est le même problème)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  6. #6
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Citation Envoyé par oodini Voir le message
    En l'occurrence, je travaille sur une classe qui représente un coût. Ce coût comprend différentes valeurs scalaires, de type différent, qui se complètent. J'ai une autre classe de coût qui ajoute des composantes scalaires, et qui hérite donc de la première classe.
    Le problème survient a mon sens quand on se retrouve à faire des copies qui change le typage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cout cout = unCoutDerive;
    Ça peut être gênant au sens où ça dénature ton coût, mais il me semble que c'est pas toujours catastrophique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    // projection renvoyant un PointSurPolyligne, dérivé de point
    Point point = projection( polyligne, point ) ;

  7. #7
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Et justement, qui dit sémantique de valeur, dit copie. Et avec l'héritage, cela dit slicing.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Vos réponse m'éclairent pas mal, mais admettons que j'ai des classes pour représenter le cout d'un salarié pour une entreprise.
    Disons que la classe de base, pour les employés standard, appelée CoûtSalarié, comporte comme données le salaire et les tickets restaurants.
    Il ne me paraît pas délirant d'avoir une classe dérivée CoûtSalariéPrimé, pour les commerciaux par exemple, qui auraient en plus une données concernant le montant des primes.

    Le cout d'un salarié sujet aux primes est bien une spécialisation d'un salarié. Sémantiquement, l'argument qui m'a été présenté ne me semble pas toujours valide.

    Seul l'argument technique reste pleinement valide. Mais il faudrait peut-être expliciter cela dans la FAQ (ou du moins ne pas présenter cela comme une évidence).

    L'héritage privé me semble être un bon compromis.

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Pour moi, il y a une erreur de modélisation. Le cout d'un salarié est une table associative (aka dictionnaire dans les langages de scripts à la mode). Cela permet de rajouter facilement de nouveaux champs.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Citation Envoyé par oodini Voir le message
    Vos réponse m'éclairent pas mal, mais admettons que j'ai des classes pour représenter le cout d'un salarié pour une entreprise.
    Disons que la classe de base, pour les employés standard, appelée CoûtSalarié, comporte comme données le salaire et les tickets restaurants.
    Il ne me paraît pas délirant d'avoir une classe dérivée CoûtSalariéPrimé, pour les commerciaux par exemple, qui auraient en plus une données concernant le montant des primes.

    Le cout d'un salarié sujet aux primes est bien une spécialisation d'un salarié. Sémantiquement, l'argument qui m'a été présenté ne me semble pas toujours valide.

    Seul l'argument technique reste pleinement valide. Mais il faudrait peut-être expliciter cela dans la FAQ (ou du moins ne pas présenter cela comme une évidence).

    L'héritage privé me semble être un bon compromis.
    Tu confonds la valeur du cout et le system qui calcul cette valeur. Les deux devraient etre dissocies. Le cout devrait avoir semantique de valeur (peut etre differents types pour differents types de couts, composes via heritage prive et "using", ou encore via CRTP) tandis que le systeme qui calcul le dis coup pourrait faire partie d'une hierarchie ou il y aurait specialization.

    Tout mettre dans la meme classe c'est pas du tout une bonne idee.

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Je n'ai nulle part parlé de système de calcul des coûts.

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 13/10/2008, 20h26
  2. connaitre la valeur sémantique d'un string
    Par vanhel dans le forum Langage
    Réponses: 4
    Dernier message: 20/05/2008, 14h32
  3. Sémantique de valeur et bosst::shared_ptr
    Par bolhrak dans le forum Boost
    Réponses: 1
    Dernier message: 11/09/2007, 00h35
  4. [VB.NET]Héritage : valeur d'une propriété perdue
    Par denilson dans le forum Windows Forms
    Réponses: 1
    Dernier message: 06/07/2006, 11h50

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