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 :

problème d'héritage en c++


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 35
    Par défaut problème d'héritage en c++
    Bonjour à tous (bonsoir plutot )
    Voila j'ai un petit soucis dont je n'arrive pas à trouver la solution.

    Je suis actuellement en train de découvrir le c++ et viens de me lancer dans l'héritage.
    Jusque la tout ce passait à peu près normalement sauf que je n'arrive pas à acceder à une methode de ma classe mère.. Et je ne sais pas trop pourquoi..

    Voici le code :
    Je vous explique après ce qui cloche ..

    Main.cpp
    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
     
    #include <cstdlib>
    #include <iostream>
    #include "personnes.h"
    #include "etudiants.h"
     
    using namespace std;
     
    int main(void)
    {
        int i = 1;
        Personnes fontm(i,"Font","Mic","contact@fontmic.truc");
        i++; // on incremente l'identifiant
        Personnes fontn(i,"Font","Nic","fontnic@yahoo.fr");
        i++; // on incremente l'identifiant
        fontm.getInfos();
        fontn.getInfos();
        cout << endl;
        cout << "** Changement de l'email fontn" << endl;
        cout << endl;
        fontn.setMail("fonfonnini@yahoo.fr");
        fontn.getInfos();
     
        // -- on va essayer maintenant de spécifier tout ça et de faire un étudiant :) 
     
        cout << endl;
        cout << "****************************" << endl;
        cout << "** Creation d'un Etudiant : " << endl;
        cout << "****************************" << endl;
        cout << endl;
     
        Etudiants gab(i,"La","Gab","ga@hotmail.fr",2006,false);
        i++; // on incremente l'identifiant
        gab.getInfos();
     
        // va laisser le temps à l'utilisateur de lire les informations et va attendre 
        // une action de sa part
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    Personnes.h
    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
     
    #ifndef _PERSONNES_H_
    #define _PERSONNES_H_
     
    class Personnes
    {
    	private : 
                int identifiant;
                char * nom, * prenom, * mail; // attention de bien mettre * devant chaque chaine
        public:
    		// constructeurs
    		Personnes(); // par defaut
    		Personnes(int &,char*,char*,char*); // par initialisation
    		Personnes(const Personnes &); // par copie
    		// destructeur
    		~Personnes();
    		// methodes de la classe
    		void getInfos(); // acceder aux informations de la personne
    		void setNom(char *); // changer son nom
    		void setPrenom(char *); // changer son prenom
    		void setMail(char *); // changer son mail
    		// notons que nous ne changerons pas son identifiant qui est unique
    };
     
    #endif
    Personnes.cpp
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    #include <iostream>
    #include "personnes.h" 
     
    using namespace std;
     
    // ****************************************************************************
    // *********** debut de la déclaration des constructeurs destructeur **********
    // **************************************************************************** 
     
    // constructeur par defaut
    Personnes::Personnes()
    {
    	identifiant = 1;
    	nom = "defaut";
    	prenom = "defaut";
    	mail = "defaut@defaut.fr";
    }
     
    // constructeur par initialisation
    Personnes::Personnes(int & ident, char * name, char * firstname, char * courriel)
    {
        identifiant = ident;
        nom = name;
        prenom = firstname;
        mail = courriel;                         
    }
     
    // constructeur par copie
    Personnes::Personnes(const Personnes & pers)
    {
        identifiant = pers.identifiant;
        nom = pers.nom;
        prenom = pers.prenom;
        mail = pers.mail;                          
    }
     
    // destructeur
    Personnes::~Personnes()
    {
    }
     
    // ***************************************************************************
    // *********** debut de la déclaration des methodes **************************
    // ***************************************************************************
     
    // permettra l'affichage des informations des personnes
    void Personnes::getInfos()
    {
         cout << " ---------------------------------------------------------- " << endl;
         cout << " -- Informations relatives a :" << nom << " " << prenom << endl;
         cout << " -- Identifiant : " << identifiant << endl;
         cout << " -- Mail : " << mail << endl;      
    } 
     
    // permettra la modification du nom de la personne
    void Personnes::setNom(char * newname)
    {
         nom = newname;     
    }
     
    // permettra la modification du prenom de la personne
    void Personnes::setPrenom(char * newpren)
    {
         prenom = newpren;     
    }
     
    // permettra la modification du mail de la personne
    void Personnes::setMail(char * newmail)
    {
         mail = newmail;     
    }
    Etudiants.h
    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
     
    #ifndef _ETUDIANTS_H_
    #define _ETUDIANTS_H_
     
    #include "personnes.h" // fichier d'entete herite
     
    class Etudiants : public Personnes
    {
        private :   
                int promotion;
                bool boursier;
                char * vraifaux;
     
                // tableau de float contenant les notes
     
    	public:
    		// constructeurs
    		Etudiants(); // par defaut
    		Etudiants(int &,char*,char*,char*,int,bool); // constructeur par initialisation
    		Etudiants(const Etudiants &); // constructeur par defaut
    		~Etudiants(); // destructeur
     
    		void getInfos(); // accès aux nouvelles informations ainsi qu'aux précédentes
    		void setBourses(bool); // modification des bourses
    		void addNotes(int,float); // ajout de notes
    };
     
    #endif // _ETUDIANTS_H_
    Et enfin Etudiants.cpp
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    #include <iostream>
    #include "etudiants.h"
    #include "personnes.h"
     
    using namespace std;
     
    // *********************************************************************
    // *********** Déclaration des constructeurs et destructeurs ***********
    // *********************************************************************
     
    // constructeur par défault
    Etudiants::Etudiants()
    {
    	Personnes(); // création d'une personne vide
        promotion = 2006; // complement d'informations
        boursier = false; // complement	d'informations
    }
     
    // constructeur par initialisation
    Etudiants::Etudiants(int & ident, char * name, char * firstname, char * email, int promo, bool bours)
    {
        Personnes(ident,name,firstname,email);
        promotion = promo;
        boursier = bours;                         
    }
     
    // constructeur par copie
    Etudiants::Etudiants(const Etudiants & e)
    {
        Personnes((Personnes) e);
        promotion = e.promotion;
        boursier = e.boursier;                       
    }
     
    // destructeur
    Etudiants::~Etudiants(){}
     
    // *********************************************************************
    // *********** Déclaration des méthodes diverses à la classe ***********
    // *********************************************************************
    void Etudiants::getInfos()
    {
         // test pour l'affichage en texte du status de boursier ou non
         if(boursier == false)
         {
                 vraifaux = "non";                
         }
         else
         {
                 vraifaux = "oui";     
         }
        this->Personnes::getInfos(); // accède normalement aux informations de la personne
        cout << " -- Promotion : " << promotion << endl; // affichage supplémentaire 
        cout << " -- boursier ? : " << vraifaux << endl; // affichage supplémentaire                
    }
    |
    |
    \ /

    Pour résumer
    Tout ce passe dans cette petite méthode
    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
     
    void Etudiants::getInfos()
    {
         // test pour l'affichage en texte du status de boursier ou non
         if(boursier == false)
         {
                 vraifaux = "non";                
         }
         else
         {
                 vraifaux = "oui";     
         }
        this->Personnes::getInfos(); // accède normalement aux informations de la personne
        cout << " -- Promotion : " << promotion << endl; // affichage supplémentaire 
        cout << " -- boursier ? : " << vraifaux << endl; // affichage supplémentaire                
    }
    Comme vous pouvez le voir dans le main je créer un nouvel étudiant avec certaines informations.
    Par la suite je construis une nouvelle personne avec ces mêmes informations, et je complete avec les informations de mon étudiants..
    J'aimerais afficher les info de la personne et les info complementaires.
    C'est ici que ça beugue, il m'affiche bien les info de la personne, mais prend les information du constructeur par défaut.
    En gros ça m'affiche ça


    ...
    blabla des autres trucs d'avant qui fonctionnent ...
    ...

    ----------------------------------------------------------
    -- Informations relatives a : defaut defaut
    -- Identifiant : 1
    -- Mail :defaut
    -- promotion : 2006
    -- boursier : non
    Comme vous pouvez le constater ce n'est pas ce que je recherche.
    La classe personne fonctionne correctement
    J'ai essayer avec et sans le this-> devant Personnes::getInfos() de mon GetInfos d'Etudiants.
    Savez vous pourquoi cette drole de chose m'arrive t'elle?

    En vous remerciant d'avance j'espère que vous saurez m'indiquer une réponse.
    Merci..
    Bonne nuit à vous

  2. #2
    Membre averti
    Inscrit en
    Août 2006
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 16
    Par défaut
    as-tu essayé dans ta classe hérité de désactivé l'appel du constructeur de la classe personne ?

  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
    Hum... Reprends tranquillement le C++. Tu es passé à côté des bases. Ta gestion des chaines de caractères est complètement à l'ouest.
    Faisons simple et correct => utilise le type standard, à savoir std::string. Cf la FAQ ou un vrai cours pour débutants qui en parlera avant les char* (qui auraient dû être constants -- et l'int, pas une référence !).

    Pour ton problème. Appelles le constructeur d'initialisation de ta classe personne depuis la classe étudiant. Cela se fait dans la liste d'initialisation. Et nulle par ailleurs ; je précise au vu de ton constructeur de recopie qui ne fera rien de bon.
    Sans le recours à la liste d'initialisation, le constructeur par défaut est systématquement appelé. Ce que tu observes est normal. Pour esquiver ce genre de bourdes, j'ai tendance à ne jamais proposer de constructeur par défaut, et encore moins de mutateurs pour des données que l'on est à même de connaitre avant la construction. Le code est plus simple, plus compact, et permet de déclarer des données non mutables.


    Choses qu'il te faudra corriger -- pour le prochain chapitre j'imagine : ta fonction getInfo() devra être virtuelle, de même que le destructeur.

    Concernant le constructeur de recopie, chose que les cours oublient de préciser : c'est rarement compatible avec l'héritage public. Et de toutes façons rarement d'un grand intérêt quand on a une sémantique d'entité. La bonne façon de faire, ici, est:
    - l'opération d'affectation, déclaré privé, mais non défini
    - le constructeur de recopie protégé (si besoin de duplication avéré)
    - une fonction de clonage publique qui appelle le constructeur de recopie protégé (si besoin de duplication avéré)
    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 averti
    Inscrit en
    Novembre 2006
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 35
    Par défaut
    Bonjour bonjour
    Merci pour ces petites réponses et surtout toi Luc, c'est vraiment ce qui me fallait, un petit point explicatif sur mes principals défauts. Je t'en remercie

    En ce qui concerne mon majeur problème c'est bien la liste d'initialisation qu'il me fallais, en plus c'est drôle je les aient utilisées dans toutes mes autres petits programmes mais la je me suis dis, tiens ça fonctionnera pas ...
    Raté
    Merci encore

    Sinon en ce qui concerne de changer mes char * en String, j'ai été piocher un peu dans la FAQ pour voir les principales différences. C'est vrai qu'elles sont nombreuses mais j'ai eu une toute petite phrase qui m'a fais un peu peur et que je n'arrive pas à comprendre

    " Même en C++ on est parfois obligé d'utiliser des char *. "

    Ma question est simple .. quand?
    J'ai tout de même fais ma mutation de char * à string sans problèmes

    Enfin une derniere petite question, c'est bien la getInfos() dans la classe fille qui dois être virtuelle, ce du fait que la classe mère porte déjà une classe de ce nom et que c'est simplement un complément d'informations. Sachant que dés lors qu'une classe comporte une fonction virtuelle, elle doit rentre son destructeur virtuel, ce sera le destructeur d'Etudiants qui sera virtual lui aussi. C'est bien ça professeur ?

    En tout cas merci encore pour cette réponse

  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
    Citation Envoyé par micfont999
    (a-) Merci pour ces petites réponses et surtout toi Luc, c'est vraiment ce qui me fallait, un petit point explicatif sur mes principals défauts. Je t'en remercie

    (b-) Sinon en ce qui concerne de changer mes char * en String, j'ai été piocher un peu dans la FAQ pour voir les principales différences. C'est vrai qu'elles sont nombreuses mais j'ai eu une toute petite phrase qui m'a fais un peu peur et que je n'arrive pas à comprendre

    " Même en C++ on est parfois obligé d'utiliser des char *. "

    Ma question est simple .. quand?
    J'ai tout de même fais ma mutation de char * à string sans problèmes

    (c-) Enfin une derniere petite question, c'est bien la getInfos() dans la classe fille qui dois être virtuelle, ce du fait que la classe mère porte déjà une classe de ce nom et que c'est simplement un complément d'informations.

    (d-) Sachant que dés lors qu'une classe comporte une fonction virtuelle, elle doit rentre son destructeur virtuel, ce sera le destructeur d'Etudiants qui sera virtual lui aussi. C'est bien ça professeur ?
    a- Avec plaisir.

    b-
    * Essentiellement quand on a besoin de dialoguer avec une API à la C non const-correcte.

    * Et aussi, quand on a du code existant sur lequel on doit se greffer qui va nous poser des problèmes avec des string (car il voudra faire des malloc/new/XMLString::alloc ; car il s'attendra à ce que l'on fasse des free/delete[]/XMLSting::release ; ...) Chose qui n'empêche pas d'utiliser du char* au niveau de l'interface, mais du std::string en interne.

    * De temps à temps on veut bidouiller au plus proche de la machine (si je puis dire), ou optimiser certains points pour proposer des alternatives plus efficaces à std::string dans des contextes bien définis. Les char* sont les trucs de plus bas niveau qui sont au coeur de ces classes de chaînes de caractères.
    Quand on part dans cette direction, on essaie de faire en sorte que quelqu'un qui a une maitrise suffisante le langage étende la bibliothèque du projet, tandis que les autres développeurs utilisent sans avoir à rentrer dans les détails.

    c- En C++, une fonction virtuelle doit être connue pour être virtuelle dès sa première déclaration : dans la classe mère.

    d- C'est une bonne première approximation. (Il y a des cas, que tu auras tout le temps de voir plus tard, où le destructeur est protégé et non virtuel -- Mais ce n'est absolument pas le cas des classes que tu nous as montré)
    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 confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut
    Salut,
    pour les char *, je dirais quand tu as besoin de meilleurs performances (mais bon la c'est vraiment si tu développes quelque chose ou le temps d'execution est primordial).

    Pour la fonction virtuelle, c'est dans la classe MERE !
    En fait une classe fille c'est juste une spécialisation de la classe mere.
    En déclarant getInfo virtuelle dans la classe Mere, tu peux la redéfinir dans les classes filles (ou non, suivant les cas).
    Donc après si tu es sur une classe fille, la methode getInfo de la classe fille sera appelé (si elle a été redéfinie, sinon c'est celle de la classe mère).

    Il faut savoir que quand tu hérites, la classe fille hérite aussi des fonctions (public et protected). Donc ici tu as deux getInfos dans la classe etudiants : celle de la classe mere et celle de la classe etudiant.

    De plus dès que tu as une fonction virtuelle, il te faut un destructeur virtuel aussi. Voir la FAQ C++

    EDIT: grillé

  7. #7
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 35
    Par défaut
    Et bin j'en est appris plus en trois messages sur un forum, qu'en 3 mois de cours à la fac mdr.
    Pourtant je suit les cours et je suis attentif, mais faut croire que vous avez une façon bien plus simple et compréhensible pour expliquer
    Merci encore à vous deux, très franchement vous m'avez bien aidé et j'ai pu comprendre certains trucs que je n'arrivais pas trop à piger

    Merci à vous deux, encore une fois
    Dommage qu'on ne puisse pas vous mettre des petites notes à chaque fois que vous aidez quelqu'un ^^
    Système à prévoir ça

    Bon je m'attaque à faire une petite classe friend de sondage des étudiants pour voir comment ça marche cte bebete, une ou deux surcharge d'opérateurs pour me mettre dans le bain, et après je m'en va retourner à mon php5 lol

    Merci à vous encore une fois, ça fais plaisir de voir que l'on peux tomber sur des personnes qui nous explique tranquillement les choses et qui ne vous disent pas, google est ton amis

    Et pi the suis un bon élève lol

    Merci encore

Discussions similaires

  1. [C#] Problème d'héritage, aide svp :(
    Par choas dans le forum Windows Forms
    Réponses: 12
    Dernier message: 06/05/2006, 11h46
  2. problème constructeur + héritage
    Par BOLARD dans le forum C++
    Réponses: 10
    Dernier message: 13/04/2006, 08h11
  3. [AS2] Problème d'héritage
    Par wwave dans le forum ActionScript 1 & ActionScript 2
    Réponses: 2
    Dernier message: 27/01/2006, 09h26
  4. Problème d'héritage ?
    Par Romanops dans le forum WinDev
    Réponses: 2
    Dernier message: 16/11/2005, 17h18
  5. Problème d'héritage d'une méthode protégée
    Par shenron666 dans le forum C++
    Réponses: 9
    Dernier message: 28/04/2005, 23h17

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