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 :

Méthodes virtuelles (again)


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 17
    Points : 17
    Points
    17
    Par défaut Méthodes virtuelles (again)
    Bonjour !

    J'ai lu pas mal de tutoriels sur le sujet des méthodes virtuelles, mais j'avoue buter sur un problème venu de l'espace (dont la solution, comme d'habitude, doit être évidente...).

    J'ai deux classes "Livre" et "Article" qui héritent de la classe de base "Document". Document contient une méthode virtuelle afficher(), implémentée par ses deux filles.

    J'ai une classe "Biblio" qui contient une "list<Document>", où j'ajoute des livres et des articles.

    Cependant, quand je prend un objet de cette liste (que je parcours avec un "iterator") et que j'appelle ), c'est la méthode afficher() de la classe mère qui est appelée !

    Je croyais avoir compris le système des méthodes virtuelles, mais là j'avoue ne rien y comprendre. J'ai pas mal planché sur ce problème, mais je ne vois pas :

    • it est bien un pointeur vers un objet "Article" ou "Livre"
    • Ce sont bien des instances des classes filles que j'ai "push_back"
    • Mes méthodes ont bien été déclarées "virtual" dans le .h de la classe mère (et des classes filles au cas où).


    Non, sérieusement, je ne vois pas... Je suppose que dans ma "list" il doit y avoir un moment où mes instances de classes filles deviennent des "Document", mais comment ?

    Je vous remercie par avance, et encore félicitations pour ce forum qui m'a tant aidé par le passé

    Mithryl.

    PS : Voici les extraits de code des fonctions

    Biblio.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    void ajouter(Document *D);
    void afficher();
    Biblio.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void Biblio::ajouter(Document *D){
    	tab.push_back(*D);
    }
    void Biblio::afficher(){
    	for (list<Document>::iterator it = tab.begin(); it !=tab.end(); it++)
    		it->afficher();
    }
    Article.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    virtual void afficher() const;
    Article.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Article::afficher() const{
    	this -> Document::afficher();
    	cout << "Revue : " << revue << endl;
    	cout << "Editeur : " << editeur << endl;
    	cout << "Numero d'édition : " << numeroEdition << endl << endl;
    }
    Document.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual void afficher() const;
    Document.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Document::afficher() const{
    	cout << endl << "DOCUMENT : " << endl;
    	cout << "Titre : " << titre << endl;
    	cout << "Resume : " << *resume <<endl;
    	cout << "Auteur : " << auteur <<endl;
    }
    Et enfin, le main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Article* article = new Article("Titre", new string("Resume"), "Auteur", "Revue", "Editeur", 2005);
    Livre* livre = new Livre("TitreL", new string("ResumeL"), "AuteurL", "EditeurL", 2010);
     
    Biblio* biblio = new Biblio();
     
    biblio->ajouter(article);
    biblio->ajouter(livre);
    biblio->afficher();
    J'ai omis quelques fonctions (constructeurs, etc) et quelques fichiers (Livre.cpp, ...), si vous en avez besoin je vous mettrai le tout

  2. #2
    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 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    le polymorphisme nécessite l'utilisation de pointeur ou référence.
    Tu as un tableau de Document, ce n'est pas bon.

    Btw, pourquoi réaliser une instanciation dynamique à base de new pour le déférencer derrière ?! Surtout avant de l'insérer par copie dans un tableau de Document.
    En plus de fuites mémoires.
    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.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 17
    Points : 17
    Points
    17
    Par défaut
    Bonjour,

    Et merci pour la rapidité de votre réponse !

    Si j'ai bien compris, dans l'absolu j'aurai dû prendre une list<Document*> ou list<Document&> ?

    Par contre je ne vois pas où il y a fuite mémoire, c'est parce que j'alloue un espace mémoire pour un pointeur (new Article) et que je stocke l'article dans une liste ?

    En fait, quand j'avais lu qu'il fallait utiliser des pointeurs ou des références pour le polymorphisme, je pensais être dedans en faisant :
    Car it est un pointeur, pourquoi n'est-ce pas bon ?

    Merci encore pour cette réponse

    Mithryl

  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 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    it est une sorte de pointeur, vers un élément de la liste.
    Si ta liste contient des Document, il ne s'agira jamais de Document*.

    Par contre je ne vois pas où il y a fuite mémoire, c'est parce que j'alloue un espace mémoire pour un pointeur (new Article) et que je stocke l'article dans une liste ?
    à chaque new doit correspondre un delete.
    mais l'allocation dynamique ne sert à rien ici.
    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
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 17
    Points : 17
    Points
    17
    Par défaut
    C'était donc ça !

    Je pensais qu'un iterator sur une list<Document> devenait un Document*, et ben non

    Merci, je me penche dessus et je viens faire mon bilan,

    Merci énormément !

    Mithryl

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    En fait, tu n'es pas loin, un iterateur est bien un équivalent de Document*.
    Pour être précis, dans un vector<T>, (*it) est un T

    Le problème est ailleurs, dans le vector, qui copie les valeurs dans un tableau interne.
    C'est à dire: vector<T>::push_back(const T& t) a plus ou moins pour code internal_array[back_index]=t;.

    L'effet est nommé slicing, (troncature?). les deux seuls contournement du slicing sont les pointeurs et les références, mais un vecteur ne peut pas être templaté sur des références.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    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 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Mithryl Voir le message
    Je pensais qu'un iterator sur une list<Document> devenait un Document*, et ben non
    Oui, mais si ton vector contient des Document, ce sont des Document. Et un Document* ne sera rien d'autre qu'un pointeur sur Document et n'aura absolument aucune chance de se transformer par magie en Article*.
    Il te faut connaître les notions de typage statique et dynamique.
    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.

  8. #8
    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 leternel Voir le message
    En fait, tu n'es pas loin, un iterateur est bien un équivalent de Document*.
    Pour être précis, dans un vector<T>, (*it) est un T

    Le problème est ailleurs, dans le vector, qui copie les valeurs dans un tableau interne.
    C'est à dire: vector<T>::push_back(const T& t) a plus ou moins pour code internal_array[back_index]=t;.

    L'effet est nommé slicing, (troncature?). les deux seuls contournement du slicing sont les pointeurs et les références, mais un vecteur ne peut pas être templaté sur des références.
    En fait, un itérateur est un objet qui permet de parcourir les éléments d'une collection.

    Il se fait que la syntaxe qui leur est associée ressemble très fort à la syntaxe que l'on associe aux pointeurs, mais il ne faut malgré tout pas confondre: un itérateur n'est pas un pointeur.

    Si tu veux pouvoir profiter du polymoprhisme dans une collection d'objets, il faut que la collection maintienne des pointeurs (que ce soit un vector<T*> ou une list<U*>) car, si tu place des objets dans ta collection (que tu utilises vector<T>), la partie qui sera copiée dans ta collection ne correspondra qu'à la partie de la classe de base.

    Par contre, il n'y a pas moyen de placer une référence sur un objet dans une collection, parce qu'une référence n'est jamais qu'un alias pour l'objet référencé.

    Enfin, je ne saurais trop conseiller d'utiliser les pointeurs intelligents de boost ou ceux fournis par C++11 (si disponibles) pour gérer les pointeurs.

    Cela évitera bien des problèmes relatifs à la gestion manuelle de la mémoire

    Ah, une petite remarque au passage: typiquement, les classes qui interviennent dans une hiérarchie de classes ont sémantique d'entité et ne devraient donc être ni affectables ni copiables.

    L'utilisation de pointeurs (et de l'allocation dynamique), de préférence intelligents, est donc parfaitement sensée dans ce cadre
    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

  9. #9
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par koala01 Voir le message
    typiquement, les classes qui interviennent dans une hiérarchie de classes ont sémantique d'entité et ne devraient donc être ni affectables ni copiables.
    Je ne suis pas sûr de bien comprendre. Selon toi, s'il y a hiérarchie alors on ne peut avoir avoir de sémantique de valeur?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  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
    Citation Envoyé par r0d Voir le message
    Je ne suis pas sûr de bien comprendre. Selon toi, s'il y a hiérarchie alors on ne peut avoir avoir de sémantique de valeur?
    On peut envisager certaines exceptions, mais, oui, si tu as une hiérarchie de classes, on peut partir du principe qu'elles ont sémantique d'entité et qu'elles n'auront absolument jamais sémantique de valeur
    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
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    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 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par koala01 Voir le message
    On peut envisager certaines exceptions, mais, oui, si tu as une hiérarchie de classes, on peut partir du principe qu'elles ont sémantique d'entité et qu'elles n'auront absolument jamais sémantique de valeur
    Je ne vois pas trop le rapport entre héritage et une non-sémantique de valeur :
    - un entier est un nombre relatif qui est un nombre rationnel qui est un nombre réel qui est un nombre complexe.
    - une suite linéaire est une suite affine.

    Je vois mal un cas où une hiérarchie de classe serait incompatible avec une sémantique de valeur.

  12. #12
    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 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    J'ai l'approche inverse : je vois pas où se situe le bénéfice et la logique d'un héritage pour une sémantique de valeur.

    Une classe d'entité, pour moi, c'est un ensemble de service qu'elle peut rendre, peu importe ce qu'elle a en interne. Ce qui importe c'est son interface.
    Une classe de valeur, c'est l'exacte opposé : ce qu'elle stocke m'intéresse, d'avantage que les éventuels services qu'elle peut rendre.
    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.

  13. #13
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    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 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Bousk Voir le message
    J'ai l'approche inverse : je vois pas où se situe le bénéfice et la logique d'un héritage pour une sémantique de valeur.

    Une classe d'entité, pour moi, c'est un ensemble de service qu'elle peut rendre, peu importe ce qu'elle a en interne. Ce qui importe c'est son interface.
    Une classe de valeur, c'est l'exacte opposé : ce qu'elle stocke m'intéresse, d'avantage que les éventuels services qu'elle peut rendre.
    La sémantique de valeur n'empêche pas une encapsulation.
    On peut utiliser le polymorphisme pour mes nombres, par exemple, en ayant une méthode virtuelle toString() redéfinie dans chaque classes filles ainsi je peux avoir une méthode prenant en paramètre 2 nombres et qui affiche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void multiplication(const Nombre & nb1, const Nombre & nb2)
    {
          nb1.toString() + " + " + nb2.toString() + " = " + (nb1 + nb2).toString;
    }
    En ayant défini par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Entier : public Relatif
    {
           Entier operator+(const Entier & ){ ... }
           template <typename T>
           T operator+(const T & other)
            {
                     return (other + *this);
             }
    }

  14. #14
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    De façon plus générale, il y a un pattern que j'ai utilisé plusieurs fois, et qui consiste à avoir un polymorphisme sur des paramètres de fonctions, paramètres ayant une sémantique de valeur.

    Typiquement, on a une fonction f( Param const * param);
    Avec l'implémentation de Param qui va ressembler à quelque chose comme ça:
    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
    class Param
    {
    public:
       double GetValue() { return value_; } 
       void DoSomethingThatModifyValue() {} // implémentation par défaut pour respecter NVI
    private:
       double value_;
    };
     
    class ParamType1 : public Param
    {
    public:
       void DoSomethingThatModifyValue() { value_ = /*code 1*/ }
    };
     
    class ParamType2 : public Param
    {
    public:
       void DoSomethingThatModifyValue() { value_ = /*code 2*/ }
    };
    Je ne sais pas si mon exemple est clair. L'idée c'est de pouvoir manipuler une valeur dans la même fonction, malgré le fait que cette valeur puisse avoir des comportement différents. Par exemple, une fréquence, selon dans quelle hauteur on est (infrason <--> ultrasons) certains calculs peuvent être différents selon les besoins.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  15. #15
    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
    En fait, j'ai écrit qu'il y avait peut etre des exceptions pour laisser la discussion ouverte, mais aucun des exemples que l'on m'a proposé jusqu'à présent ne m'a réellement convaincu (et je crains même qu'aucun exemple ne me convaincra jamais )

    Mais prenons peut etre le problème dans l'autre sens.

    Une classe ayant sémantique de valeur a pour caractéristiques principales
    1. de ne pas être unique (il peut y avoir plusieurs instances présentant une valeur similaires en mémoire)
    2. d'être copiable (ce qui n'est qu'une dérivation de la première caractéristique )
    3. d'être affectable
    4. d'être comparable, au minimum par égalité
    alors qu'une classe ayant sémantique d'entité a pour caractéristiques principale
    1. D'être identifiable de manière unique et non ambigüe (ne serait-ce qu'au niveau de son adresse mémoire)
    2. de ne pas être affectable
    3. de ne pas être copiable
    4. de ne pas être comparable par égalité (même si certains attributs peuvent l'être séparément)
    Je n'ai, à ce jour, jamais croisé une classe qui tout à la fois
    • intervienne dans une hiérarchie de classe
    • présente les caractéristiques intrinsèques d'une classe ayant sémantique de valeur
    • respecte les principes de conception orientée objets (dont LSP en priorité)
    et j'attends toujours qu'on me présente un exemple cohérent qui agisse de la sorte

    @r0d > Ton exemple de paramètre me semble rentrer beaucoup plus dans la catégorie de classe ayant sémantique d'entité que dans celle ayant sémantique de valeur, car tes paramètres présentent les caractéristiques que j'ai citées pour ce cas, non

    @Neckara> Le rapport entre héritage et non sémantique de valeur est pourtant relativement simple:

    Lorsque tu recours à l'héritage, toutes les instances des différentes classes sont identifiables de manière unique et non ambigües (entre autres caractéristiques), avec tout ce que cela implique.

    Cette seule caractéristique fait déjà que l'on ne peut pas considérer que ces classes ont sémantique de valeur, car l'une des caractéristiques principales des classes qui sont dans ce cas est de pouvoir exister en plusieurs exemplaires en mémoire
    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

  16. #16
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    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 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par koala01 Voir le message
    @Neckara> Le rapport entre héritage et non sémantique de valeur est pourtant relativement simple:

    Lorsque tu recours à l'héritage, toutes les instances des différentes classes sont identifiables de manière unique et non ambigües (entre autres caractéristiques), avec tout ce que cela implique.
    J'ai du mal à comprendre...
    On peut identifier toutes les instances de manière unique et non ambigües avec leur adresse, qu'on ai une entité ou une valeur.

    De plus cela signifierais que la sémantique de valeur n'existe pas en Java (en dehors des types de bases int) puisque tout hérite de Object ?

  17. #17
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par koala01 Voir le message
    @r0d > Ton exemple de paramètre me semble rentrer beaucoup plus dans la catégorie de classe ayant sémantique d'entité que dans celle ayant sémantique de valeur, car tes paramètres présentent les caractéristiques que j'ai citées pour ce cas, non
    Je ne pense pas -> lire la suite.

    Citation Envoyé par koala01 Voir le message
    Lorsque tu recours à l'héritage, toutes les instances des différentes classes sont identifiables de manière unique et non ambigües (entre autres caractéristiques), avec tout ce que cela implique.
    En fait c'est ça que je ne comprend pas. En quoi une classe non polymorphe serait moins identifiable qu'une classe polymorphe?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  18. #18
    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
    En fait c'est ça que je ne comprend pas. En quoi une classe non polymorphe serait moins identifiable qu'une classe polymorphe?
    Ce n'est pas un facteur de cause à effet, mais de cause commune.
    La classe à sémantique de valeur se transmet par copie, ou elle n'est pas à sémantique de valeur.

    Le dernier code que tu as posté correspond à une sémantique d'entité, je suis d'accord avec Koala01.

    Mais il est possible que tu changes la sémantique de ta classe selon les cas; et que tu transmets cette classe par valeur dans la plupart des autres cas. C'est un peu pour ça que je suis assez réticent à rattacher arbitrairement la sémantique valeur/entité au type lui-même, plutôt qu'à la situation.
    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.

  19. #19
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    La classe à sémantique de valeur se transmet par copie, ou elle n'est pas à sémantique de valeur.
    Ok. En fait je n'y comprend juste rien à cette histoire... c'est sans doute pour ça que je suis sceptique

    Il va falloir que je relise mes classiques; Mais bon, ça me semble tout de même très étrange tout ceci. Déjà, je ne passe aucun paramètre (de type non natif) par copie. Le plus souvent par référence constante, mais jamais par copie.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  20. #20
    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
    Citation Envoyé par Neckara Voir le message
    J'ai du mal à comprendre...
    On peut identifier toutes les instances de manière unique et non ambigües avec leur adresse, qu'on ai une entité ou une valeur.
    Oui, mais tu as la notion d'unicité:Si tu trouves quelqu'un dont le pseudo est koala01, qui est né la même date que moi, qui habite à la même adresse que moi et dont le nom est le même que le mien, tu as la garantie de parler avec moi.

    Toute personne qui aurait les mêmes caractéristiques (en ce, y compris celles qui permettent de l'identifier de manière unique et non ambigüe, autrement que par l'adresse mémoire à laquelle elle se trouve) que moi ne pourrait être... que moi

    A coté de cela, il est toujours possible d'identifier une instance donnée d'une classe ayant sémantique de valeur par l'adresse mémoire à laquelle elle se trouve, mais il est toujours possible de trouver une autre instance de cette classe, à une adresse mémoire totalement différente, et présentant exactement les mêmes caractéristiques, avec comme conséquence que l'on pourrait comparer toutes les caractéristiques (hormis l'adresse mémoire à laquelle elle se trouve ) et estimer que les deux instances sont égales, bien que n'étant pas "les mêmes" (dans le sens où elles n'ont pas la même adresse mémoire)

    Ainsi, tu peux très bien envisager d'avoir deux points représentant les mêmes coordonnées, ou deux couleurs strictement identiques et donc considérées comme égales, bien que se trouvant à des adresses mémoire totalement différentes.

    La contrainte d'unicité n'apparait donc que pour les classes ayant sémantique d'entité, et découle directement de... l'impossibilité qui est faite de copier les instances de classes de ce type.

    Bien sur, on peut envisager de cloner une instance de classe ayant sémantique d'entité, mais, à ce moment là, l'instance "originale" et l'instance "clonée" ne pourront pas être considérées comme égales, bien qu'ayant a priori toutes leurs caractéristiques identiques... Sauf une: leur adresse mémoire

    De plus cela signifierais que la sémantique de valeur n'existe pas en Java (en dehors des types de bases int) puisque tout hérite de Object ?
    Cela signifie qu'il y a très clairement un problème en java, en tout état de cause.

    Peut etre faut il en arriver, en java, à ne pas trop s'intéresser à la sémantique des classes que l'on crée

    Peut etre le simple fait que tout hérite de Object est il une monstruosité, bien que ce soit compréhensible ne serait-ce que pour permettre l'utilisation du garbage collector

    Peut etre java a-t-il, définitivement, pour objectif d'aider les idiots à concevoir des choses avec une certaine facilité (de façade)

    Peut etre java n'a-t-il simplement rien compris au concept même de la programmation orientée objets

    Je ne répondrai à aucune de ces questions, même si j'ai mon avis personnel sur chacune d'elles... Mais peut etre les gens devraient ils se les poser
    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

Discussions similaires

  1. Appel d'une méthode virtuelles
    Par BIPBIP59 dans le forum C++Builder
    Réponses: 4
    Dernier message: 24/03/2006, 14h00
  2. Méthodes virtuelle et implémentation
    Par slate dans le forum C++
    Réponses: 2
    Dernier message: 16/02/2006, 17h16
  3. méthodes virtuelles
    Par ep31 dans le forum C++
    Réponses: 2
    Dernier message: 09/11/2005, 17h21
  4. Comment l'appel à une méthode virtuelle....
    Par Blobette dans le forum C++
    Réponses: 7
    Dernier message: 07/12/2004, 13h55
  5. [C#] Méthode virtuelle
    Par jacma dans le forum Windows Forms
    Réponses: 4
    Dernier message: 07/11/2004, 08h18

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