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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 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 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    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 averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 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 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    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 averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    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.

  7. #7
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    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.

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