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 :

Plein d'erreurs dans mon code


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    183
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 183
    Par défaut Plein d'erreurs dans mon code
    Bonjour,
    J'ai fais un code d'un programme qui permet de saisir les informations du personnel dans une entreprise ( employé,cadre), mais mon code comporte beaucoup d'erreurs surtout aux niveau des constructeurs , pourvez vous m'aider ?
    Merci d'avance
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    #include <iostream>
    #include <iomanip>
    #include <string>
    using namespace std;
     
    class Personnel
    {
        int NCI;
        char Nom[20];
        char Prenom[20];
        public:
        Personnel();
        Personnel(int nc,char *nm,char *pr);
        ~Personnel();
        void saisie();
        void affichage();
    };
    Personnel::Personnel()
    {
        NCI=125;
        strcpy(Nom,"");
        strcpy(Prenom,"");
    }
    Personnel::Personnel(int nc,char *nm,char *pr)
    {
        NCI=nc;
        strcpy(Nom,nm);
        strcpy(Prenom,pr);
    }
    Personnel::~Personnel()
    {
        cout<<"Ceci est un destructeur de la classe Personnel"<<endl;
    }
    void Personnel::saisie()
    {
        cout<<"Entrez le numero de la carte d'identité"<<endl;
        cin>>NCI;
        cout<<"Entrez votre Nom"<<endl;
        cin>>Nom;
        cout<<"Entrez votre Prenom"<<endl;
        cin>>Prenom;
     
    }
    void Personnel::affichage()
    {
        cout<<"NCI= "<<NCI<<endl;
        cout<<"Nom= "<<Nom<<endl;
        cout<<"Prenom= "<<Prenom<<endl;
    }
    class Employe:public Personnel
    {
        float nb_h,tarif;
        public:
        Employe();
        Employe(int nc,char *nm,char *pr,float nh,float,tar);
        ~Employe();
        void saisie();
        void affichage();
     
     
    };
    Employe::Employe()
    {
        nb_h=0;
        tarif=10;
    }
    Employe::Employe(int nc,char *nm,char *pr,float nh,float tar):Personnel(nc,nm,pr)
    {
        tarif=tar;
        nb_h=nh;
    }
    Employe::~Employe()
    {
        cout<<"Ceci est un destructeur de la classe Employ\x82"<<endl;
     
    }
    void saisie::Employe()
    {
        Personnel::saisie();
        cout<<"Entrez le nb_h "<<endl;
        cin>>nb_h;
        cout<<"Entrez le tarif"<<endl;
        cin>>tarif;
    }
    void affichage::Employe()
    {
        Personnel::affichage();
        cout<<"nb_h= "<<nb_h;
        cout<<"tarif= "<<tarif;
    }
    class Cadre:public Employe
    {
        float salaire,prime;
        public:
        Cadre();
        Cadre(int nc,char *nm,char *pr,float sal,float pri);
        ~Cadre();
        void saisie();
        void affichage();
     
    };
    Cadre::Cadre()
    {
        salaire=100;
        prime=0;
    }
    Cadre::Cadre(int nc,char *nm,char *pr,float sal,float pri):Personnel(nc,nm,pr)
    {
        salaire=sal;
        prime=pri;
    }
    Cadre::~Cadre()
    {
        cout<<"Ceci est un destructeur de la classe Cadre"<<endl;
    }
    void saisie::Cadre()
    {
        Personnel::saisie();
        cout<<"Entrez le salaire"<<endl;
        cin>>salaire;
        cout<<"Entrez la prime"<<endl;
        cin>>prime;
    }
    void affichage::Cadre()
    {
        Personnel::affichage();
        cout<<"Salaire= "<<salaire;
        cout<<"Prime= "<<prime;
    }
    void main()
    {
        clrscr();
        cout<<"saisie une personne"<<endl;
        Personnel p;
        p.saisie();
        p.affichage();
        cout<<"saisie cadre"<<endl;
        Cadre c;
        c.saisie();
        c.affichage();
        cout<<"saisie employ\x82"<<endl;
        Employe e;
        e.saisie();
        e.affichage();
        getch();
    }

  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,

    doit-on deviner les erreurs ?
    Plein d'erreurs au niveau des constructeurs ? Mais encore ?
    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 très actif
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    183
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 183
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Bonjour,

    doit-on deviner les erreurs ?
    Plein d'erreurs au niveau des constructeurs ? Mais encore ?
    Justement ,codeblocks m'informe que l'erreur vient du constructeur mais il dit pas où exactement et j'arrive pas à trouver

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    La liste d'initialisation c'est pour les sous-objet membre, de base direct et de base virtuel. Dans ton cas Personnel n'est ni une classe de base direct ni une classe de base virtuel, de Cadre : tu n'as pas le droit d'initialiser le sous-objet de type Personnel dans la liste d'initialisation d'un constructeur de Cadre.

    Dit autrement tu n'as pas le droit d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Cadre::Cadre(/*param*/) : Personnel(/*param*/) {}

  5. #5
    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 Flob90 Voir le message
    La liste d'initialisation c'est pour les sous-objet membre, de base direct et de base virtuel. Dans ton cas Personnel n'est ni une classe de base direct ni une classe de base virtuel, de Cadre : tu n'as pas le droit d'initialiser le sous-objet de type Personnel dans la liste d'initialisation d'un constructeur de Cadre.

    Dit autrement tu n'as pas le droit d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Cadre::Cadre(/*param*/) : Personnel(/*param*/) {}
    Si, c'est ainsi qu'on appelle explicitement un constructeur de la classe parent.
    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.

  6. #6
    Membre expérimenté Avatar de Rewpparo
    Homme Profil pro
    Amateur
    Inscrit en
    Décembre 2005
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Amateur

    Informations forums :
    Inscription : Décembre 2005
    Messages : 170
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Si, c'est ainsi qu'on appelle explicitement un constructeur de la classe parent.
    Seulement pour les parents directs, tu ne peux pas court-circuiter une partie de la hiérarchie. Cadre hérite d'employé qui hérite de personnel, dans cadre il peut donc appeller le constructeur d'employé, pas de personnel. Sinon les données d'employé ne sont pas initalisées, et si emploté pose des contraintes sur personnel elles ne seront pas prises en compte.

  7. #7
    Membre très actif
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    183
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 183
    Par défaut
    Citation Envoyé par nourhene4 Voir le message
    Bonjour,
    J'ai fais un code d'un programme qui permet de saisir les informations du personnel dans une entreprise ( employé,cadre), mais mon code comporte beaucoup d'erreurs surtout aux niveau des constructeurs , pourvez vous m'aider ?
    Merci d'avance
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    #include <iostream>
    #include <iomanip>
    #include <string>
    using namespace std;
     
    class Personnel
    {
        int NCI;
        char Nom[20];
        char Prenom[20];
        public:
        Personnel();
        Personnel(int nc,char *nm,char *pr);
        ~Personnel();
        void saisie();
        void affichage();
    };
    Personnel::Personnel()
    {
        NCI=125;
        strcpy(Nom,"");
        strcpy(Prenom,"");
    }
    Personnel::Personnel(int nc,char *nm,char *pr)
    {
        NCI=nc;
        strcpy(Nom,nm);
        strcpy(Prenom,pr);
    }
    Personnel::~Personnel()
    {
        cout<<"Ceci est un destructeur de la classe Personnel"<<endl;
    }
    void Personnel::saisie()
    {
        cout<<"Entrez le numero de la carte d'identité"<<endl;
        cin>>NCI;
        cout<<"Entrez votre Nom"<<endl;
        cin>>Nom;
        cout<<"Entrez votre Prenom"<<endl;
        cin>>Prenom;
     
    }
    void Personnel::affichage()
    {
        cout<<"NCI= "<<NCI<<endl;
        cout<<"Nom= "<<Nom<<endl;
        cout<<"Prenom= "<<Prenom<<endl;
    }
    class Employe:public Personnel
    {
        float nb_h,tarif;
        public:
        Employe();
        Employe(int nc,char *nm,char *pr,float nh,float,tar);
        ~Employe();
        void saisie();
        void affichage();
     
     
    };
    Employe::Employe()
    {
        nb_h=0;
        tarif=10;
    }
    Employe::Employe(int nc,char *nm,char *pr,float nh,float tar):Personnel(nc,nm,pr)
    {
        tarif=tar;
        nb_h=nh;
    }
    Employe::~Employe()
    {
        cout<<"Ceci est un destructeur de la classe Employ\x82"<<endl;
     
    }
    void saisie::Employe()
    {
        Personnel::saisie();
        cout<<"Entrez le nb_h "<<endl;
        cin>>nb_h;
        cout<<"Entrez le tarif"<<endl;
        cin>>tarif;
    }
    void affichage::Employe()
    {
        Personnel::affichage();
        cout<<"nb_h= "<<nb_h;
        cout<<"tarif= "<<tarif;
    }
    class Cadre:public Employe
    {
        float salaire,prime;
        public:
        Cadre();
        Cadre(int nc,char *nm,char *pr,float sal,float pri);
        ~Cadre();
        void saisie();
        void affichage();
     
    };
    Cadre::Cadre()
    {
        salaire=100;
        prime=0;
    }
    Cadre::Cadre(int nc,char *nm,char *pr,float sal,float pri):Personnel(nc,nm,pr)
    {
        salaire=sal;
        prime=pri;
    }
    Cadre::~Cadre()
    {
        cout<<"Ceci est un destructeur de la classe Cadre"<<endl;
    }
    void saisie::Cadre()
    {
        Personnel::saisie();
        cout<<"Entrez le salaire"<<endl;
        cin>>salaire;
        cout<<"Entrez la prime"<<endl;
        cin>>prime;
    }
    void affichage::Cadre()
    {
        Personnel::affichage();
        cout<<"Salaire= "<<salaire;
        cout<<"Prime= "<<prime;
    }
    void main()
    {
        clrscr();
        cout<<"saisie une personne"<<endl;
        Personnel p;
        p.saisie();
        p.affichage();
        cout<<"saisie cadre"<<endl;
        Cadre c;
        c.saisie();
        c.affichage();
        cout<<"saisie employ\x82"<<endl;
        Employe e;
        e.saisie();
        e.affichage();
        getch();
    }
    Mon code fonctionne maintenant;
    Les erreurs que j'ai corrigé sont :
    * j'ai mis cstring au lieu de string
    *j'ai corrigé void saisie::Employe en void Employe::saisie , ainsi que les autres fonctions déclarées avec la même erreur
    *J'ai enlevé clrscr() pq codeblocks ne le reconnait pas
    Merci pour tous ceux qui ont aidé à la correction e mon code

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Bon, il y a vraiment de la place pour le progrès

    Ce n'est pas dit méchamment, bien sur, c'est pour t'inciter à admettre que tu as grandement intérêt à lire un minimum les réponses et à faire, peut etre bêtement dans un premier temps exactement ce que l'on te dit

    D'abord, pourrais tu nous faire un copier coller des (mettons) dix premières lignes d'erreur que t'envoie code::blocks ( En bas de la fenêtre code::blocks, dans l'onglet "build messages", clique droit sur une des lignes de l'erreur, et cliquer sur "copy content to clipboard, puis, sur le forum, <CTRL>+ V pour coller les lignes d'erreur, les resélectionner toutes et cliquer sur le bouton # en haut du formulaire pour ajouter les balises [ CODE ] qui assureront une mise en forme utile pour la relecture )

    Ensuite, ton prof n'en a peut etre pas conscience, mais C++ est un langage qui n'a strictement plus rien à voir avec C!!!

    Tout au plus permet-il dans un soucis de compatibilité de récupérer du code écrit en C, mais, a priori, rien de ce que tu code ne devrait recourir aux mécanismes issus de C

    Ainsi, on t'a parlé de la classe string, disponible dans l'espace de noms std par simple inclusion du fichier d'en-tête <string>...

    Commence déjà par utiliser cette classe à chaque fois que tu veux travailler avec des chaines de caractères, tu verras, ca te changera la vie

    Ta classe Personnel pourrait donc ressembler à (je ne m'intéresse qu'aux chaines de caractères )
    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
     
    #include <string>
    // je n'aime pas vraiment la directive using namespace ;)
    //using namespace std;
     
    class Personnel
    {
        int NoCarteIdentite;
        std::string Nom;
        std::string Prenom;
        public:
        Personnel();
        Personnel(int nc, std::sttring const & nom, std::string const & prenom);
        ~Personnel();
        void saisie();
        void affichage();
    };
    Le constructeur sera alors avantageusement modifié de manière à utiliser les listes d'initialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Personne::Personnel(int carteIdentite, std::sttring const & nom, std::string const & prenom):NoCarteIdentite(carteIdentite),Nom(nom),Prenom(prenom){}
    Tu remarqueras au passage que cela ne prend pas énormément plus de temps d'écrire "nom" ou "prenom" pour les paramètres, mais que cela te facilitera aussi la vie, ne serait-ce que parce que meme code::blocks te fournit un "tooltips" qui t'indique les paramètres que tu dois ajouter lors de l'appel de la fonction.

    Le fait de nommer correctement tes variables et tes arguments te permettra, si tu reviens sur ce code d'ici trois mois, de te rappeler beaucoup plus facilement à quoi servent tes variables et tes arguments

    Et, accessoirement, cela permettra aux intervenants du forum de comprendre ton code sans devoir passer dix minutes à déchiffrer ce que tu as écrit afin de te venir en aide

    N'oublies pas que tous les intervenants du forum (moi y compris ) sont des gens qui viennent ici sur leur temps libre, et que, comme toi, ils ont peut etre envie de profiter du beau soleil printanier

    Enfin, bref, continuons...

    La fonction Personnel::saisie ne rime strictement à rien !!!

    Tu fournis toutes les informations que la fonction saisie demande directement dans le constructeur de Personnel, il ne sert donc strictement à rien de permettre de les modifier (car, a priori, Roland Dupont n'a aucune raison de s'appeler un jour Isabelle Dubois, ni de changer de numéro de carte d'identité )

    De plus, tu donnes à ta classe Personnel une responsabilité qu'elle n'a absolument pas à avoir:

    La classe Personnel doit, en effet, s'occuper de gérer les informations du personnel, une fois qu'un objet de ce type a été créé, mais, une fois que l'objet a été créé, il est déjà beaucoup trop tard pour demander le nom, le prénom et le numéro de carte d'identité :

    Ce sont des informations dont on a absolument besoin pour pouvoir créer un objet de type personnel

    Intéressons nous maintenant aux autres classes, et, surout, à leur fonction affiche() (je considère que tu auras suivi mon conseil quant à la fonction saisie )

    Mais, avant toute chose, je vais jouer à un petit jeu de question (que je te pose) et de réponses (que tu me donnerait sans doute dans une discussion en directe) ... Tu vas voir, c'est édifiant

    Je te demanderais d'abord 'pourquoi as tu fait hériter ta classe Employe de ta classe Personnel

    Tu me répondrais surement "Ben parce qu'un employé EST-UN membre du personnel, pardi", et cela peut se comprendre

    Je te demandrais ensuite "Cela veut il bien dire que tu souhaites maintenir une collection de "membres du personnel" dans laquelle tu souhaites pouvoir placer indifféremment les différents type de membre du personnel qui existent (ex : des employés, des ouvriers, des cadres, ... )

    Et je présumes que ta réponse serait proche de "Mais oui, bien sur!!!"

    Je te demanderais alors "Et je présumes, enfin, que tu veux pouvoir transmettre un Employe à une fonction en le faisant passer pour un membre du personnel, tout en obtenant (pour la fonction membre affiche, par exemple) le comportement qui est propre à la classe Employe "

    Et là, tu me prendrait pour un dieu omniscient et tu me répondrait "Koala, t'es vraiment trop fort, tu as tout deviné tout de suite" (he... y a pas de mal à se lancer des fleurs, vu que personne ne le fera à ma place (par contre, je m'attend à recevoir les pots assez rapidement ) )

    Ma modestie naturelle reprendrait alors le dessus, et je t'expliquerais bien humblement que je ne suis "que" un mec tout à fait normal qui a appris, avec le temps, à décoder les besoins fonctionnels des gens qui posent une question sur le forum

    Puis, redevenant sérieux, je te dirais "En fait, je voulais simplement vérifier que nous étions réellement dans un cadre dans lequel l'héritage public est applicable, et cela semble etre le cas... Sauf que... ca ne marchera jamais... "

    Hé oui, on en est bien là... ton code, tel qu'il est écrit, il ne marchera jamais... ou du moins, jamais comme tu l'espères ()

    Pire, tu risques d'avoir quelques soucis au moment de la libération des ressources, et ce ne seront pas les moindres (re )

    Il y a trois mots qui, à eux seuls, expliquent la cause du problème que les autres intervenants n'ont sans doute pas remarqué (à cause d'une lecture trop hative, sans doute) et donnent en meme temps la solution : virtualité des fonctions

    Hé oui... Est il besoin de rappeler que, à l'inverse de certains autres langages (de très bonne facture au demeurant), C++ a décidé de ne pas faire payer le prix de la virtualité implicite des fonctions

    Si une fonction doit voir son comportement modifié en fonction du type réel de l'objet au départ duquel elle est invoquée, (autrement dit : si une fonction a vocation à être redéfinie dans les classes dérivées), il faut indiquer explicitement au compilateur que la fonction est virtuelle.

    Ainsi, le constructeur de la classe Personnel doit etre virtuel, autrement, lorsqu'il sera appelé depuis un pointeur de type Personnel qui pointe en réalité sur un objet de type Employe, il ne fera le ménage que de la partie "Personnel" de l'employé, en "laissant trainer" tout ce qui est propre à la partie Employe

    De même, la fonction affiche doit aussi être déclarée virtuelle, autrement, le fait de l'avoir redéfinie dans la classe Employe "cachera" la fonction d'origine, laissant à penser que "tout va bien" lorsqu'elle est invoquée depuis (un pointeur ou une référence sur) un objet employé, mais n'affichera que les information propre au membre du personnel quand elle sera invoquée depuis (un pointeur ou une référence sur) un objet "passant pour etre du type Personnel"...

    Autrement dit, voici ce qui pourrait se passer. Nous pourrions avoir un code proche de:
    i
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    nt main()
    {
        Employe employe(/* paramètres requis */);
        Employe & refEmploye = employe;      // le cas d'une référence du type réel
        Employe * ptrEmploye = &employe;     // le cas d'un pointeur du type réel
        Personnel & refPersonnel = employe;  // on peut le faire : un employe est bien un membre du personnel
        Personnel * ptrPersonnel = &employe; // idem
        employe.affiche();                   // OK, affiche correctement les données de l'employe (voir sortie plus bas)
        refEmploye.affiche() ;               // OK, diem
        ptrEmploye->affiche();               // toujours pas de problème ;)
        refPersonnel.affiche();              // KO.. c'est la version de Personnel::affiche() qui est utilisée
        ptrPersonnel->affiche();             // KO idem
        return 0;
    }
    qui donnerait une sortie proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    NCI= 125Nom= DupontPrenom= Jeannb_h= 45tarif = 18.5
    NCI= 125Nom= DupontPrenom= Jeannb_h= 45tarif = 18.5
    NCI= 125Nom= DupontPrenom= Jeannb_h= 45tarif = 18.5
    NCI= 125Nom= DupontPrenom= Jean
    NCI= 125Nom= DupontPrenom= Jean
    M'est avis que tu aimerais, en travaillant avec un pointeur ou une référence de type Personnel, obtenir exactement la meme sortie que si tu avais travaillé avec l'objet de type Employe, non

    La solution est toute simple, modifions quelque peu la définition de la classe Personnel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Personnel
    {
        int NoCarteIdentite;
        std::string Nom;
        std::string Prenom;
        public:
        Personnel();
        Personnel(int nc, std::sttring const & nom, std::string const & prenom);
        virtual ~Personnel();
        virtual void affichage();
    };
    Et cela suffirait déjà, mais, à l'instar de beaucoup de mes collègues, je préfères répéter le mot clé virtal dans les classes dérivées (bien que la norme nous autorise à ne pas le faire ), simplemnt pour que le lecteur du code puisse se rendre compte qu'il s'agit d'une fonction destinée à être redéfinie sans devoir aller voir la classe parent

    Modifions donc la définition de la classe Employe (et de la classe Cadre) de la même manière
    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
    class Employe:public Personnel
    {
        float nb_h,tarif;
        public:
        Employe();
        Employe(int carteIdentite,std::string const & nom, 
                std::string const & prenom,float nh,float,tar);
        virtual ~Employe();
        virtual void affichage();
     
     
    };
    class Cadre:public Employe
    {
        float salaire,prime;
        public:
        Cadre();
        Cadre(int carteIdentite, const std::string const & nom,
             std::string const & prenom,float sal,float pri);
        virtual ~Cadre();
        virtual void affichage();
     
    };
    Et là, ca commence enfin à ressembler à quelque chose... Au moins, le programme réagira-t-il exactement comme on est en droit de s'y attendre

    Il ne te reste "plus qu'à" trouver le moyen de donner la responsabilité de la saisie à "autre chose" qu'aux classes (descendant de ) Personnel...

    La clé se trouve dans ce que l'on appelle un "desing pattern" nomme Fabrique (Factory en anglais )

    Mais, pour ne quand meme pas faire tout ton boulot, je vais te laisser chercher un peu
    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
    Membre très actif
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    183
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 183
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    Bon, il y a vraiment de la place pour le progrès

    Ce n'est pas dit méchamment, bien sur, c'est pour t'inciter à admettre que tu as grandement intérêt à lire un minimum les réponses et à faire, peut etre bêtement dans un premier temps exactement ce que l'on te dit

    D'abord, pourrais tu nous faire un copier coller des (mettons) dix premières lignes d'erreur que t'envoie code::blocks ( En bas de la fenêtre code::blocks, dans l'onglet "build messages", clique droit sur une des lignes de l'erreur, et cliquer sur "copy content to clipboard, puis, sur le forum, <CTRL>+ V pour coller les lignes d'erreur, les resélectionner toutes et cliquer sur le bouton # en haut du formulaire pour ajouter les balises [ CODE ] qui assureront une mise en forme utile pour la relecture )

    Ensuite, ton prof n'en a peut etre pas conscience, mais C++ est un langage qui n'a strictement plus rien à voir avec C!!!

    Tout au plus permet-il dans un soucis de compatibilité de récupérer du code écrit en C, mais, a priori, rien de ce que tu code ne devrait recourir aux mécanismes issus de C

    Ainsi, on t'a parlé de la classe string, disponible dans l'espace de noms std par simple inclusion du fichier d'en-tête <string>...

    Commence déjà par utiliser cette classe à chaque fois que tu veux travailler avec des chaines de caractères, tu verras, ca te changera la vie

    Ta classe Personnel pourrait donc ressembler à (je ne m'intéresse qu'aux chaines de caractères )
    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
     
    #include <string>
    // je n'aime pas vraiment la directive using namespace ;)
    //using namespace std;
     
    class Personnel
    {
        int NoCarteIdentite;
        std::string Nom;
        std::string Prenom;
        public:
        Personnel();
        Personnel(int nc, std::sttring const & nom, std::string const & prenom);
        ~Personnel();
        void saisie();
        void affichage();
    };
    Le constructeur sera alors avantageusement modifié de manière à utiliser les listes d'initialisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Personne::Personnel(int carteIdentite, std::sttring const & nom, std::string const & prenom):NoCarteIdentite(carteIdentite),Nom(nom),Prenom(prenom){}
    Tu remarqueras au passage que cela ne prend pas énormément plus de temps d'écrire "nom" ou "prenom" pour les paramètres, mais que cela te facilitera aussi la vie, ne serait-ce que parce que meme code::blocks te fournit un "tooltips" qui t'indique les paramètres que tu dois ajouter lors de l'appel de la fonction.

    Le fait de nommer correctement tes variables et tes arguments te permettra, si tu reviens sur ce code d'ici trois mois, de te rappeler beaucoup plus facilement à quoi servent tes variables et tes arguments

    Et, accessoirement, cela permettra aux intervenants du forum de comprendre ton code sans devoir passer dix minutes à déchiffrer ce que tu as écrit afin de te venir en aide

    N'oublies pas que tous les intervenants du forum (moi y compris ) sont des gens qui viennent ici sur leur temps libre, et que, comme toi, ils ont peut etre envie de profiter du beau soleil printanier

    Enfin, bref, continuons...

    La fonction Personnel::saisie ne rime strictement à rien !!!

    Tu fournis toutes les informations que la fonction saisie demande directement dans le constructeur de Personnel, il ne sert donc strictement à rien de permettre de les modifier (car, a priori, Roland Dupont n'a aucune raison de s'appeler un jour Isabelle Dubois, ni de changer de numéro de carte d'identité )

    De plus, tu donnes à ta classe Personnel une responsabilité qu'elle n'a absolument pas à avoir:

    La classe Personnel doit, en effet, s'occuper de gérer les informations du personnel, une fois qu'un objet de ce type a été créé, mais, une fois que l'objet a été créé, il est déjà beaucoup trop tard pour demander le nom, le prénom et le numéro de carte d'identité :

    Ce sont des informations dont on a absolument besoin pour pouvoir créer un objet de type personnel

    Intéressons nous maintenant aux autres classes, et, surout, à leur fonction affiche() (je considère que tu auras suivi mon conseil quant à la fonction saisie )

    Mais, avant toute chose, je vais jouer à un petit jeu de question (que je te pose) et de réponses (que tu me donnerait sans doute dans une discussion en directe) ... Tu vas voir, c'est édifiant

    Je te demanderais d'abord 'pourquoi as tu fait hériter ta classe Employe de ta classe Personnel

    Tu me répondrais surement "Ben parce qu'un employé EST-UN membre du personnel, pardi", et cela peut se comprendre

    Je te demandrais ensuite "Cela veut il bien dire que tu souhaites maintenir une collection de "membres du personnel" dans laquelle tu souhaites pouvoir placer indifféremment les différents type de membre du personnel qui existent (ex : des employés, des ouvriers, des cadres, ... )

    Et je présumes que ta réponse serait proche de "Mais oui, bien sur!!!"

    Je te demanderais alors "Et je présumes, enfin, que tu veux pouvoir transmettre un Employe à une fonction en le faisant passer pour un membre du personnel, tout en obtenant (pour la fonction membre affiche, par exemple) le comportement qui est propre à la classe Employe "

    Et là, tu me prendrait pour un dieu omniscient et tu me répondrait "Koala, t'es vraiment trop fort, tu as tout deviné tout de suite" (he... y a pas de mal à se lancer des fleurs, vu que personne ne le fera à ma place (par contre, je m'attend à recevoir les pots assez rapidement ) )

    Ma modestie naturelle reprendrait alors le dessus, et je t'expliquerais bien humblement que je ne suis "que" un mec tout à fait normal qui a appris, avec le temps, à décoder les besoins fonctionnels des gens qui posent une question sur le forum

    Puis, redevenant sérieux, je te dirais "En fait, je voulais simplement vérifier que nous étions réellement dans un cadre dans lequel l'héritage public est applicable, et cela semble etre le cas... Sauf que... ca ne marchera jamais... "

    Hé oui, on en est bien là... ton code, tel qu'il est écrit, il ne marchera jamais... ou du moins, jamais comme tu l'espères ()

    Pire, tu risques d'avoir quelques soucis au moment de la libération des ressources, et ce ne seront pas les moindres (re )

    Il y a trois mots qui, à eux seuls, expliquent la cause du problème que les autres intervenants n'ont sans doute pas remarqué (à cause d'une lecture trop hative, sans doute) et donnent en meme temps la solution : virtualité des fonctions

    Hé oui... Est il besoin de rappeler que, à l'inverse de certains autres langages (de très bonne facture au demeurant), C++ a décidé de ne pas faire payer le prix de la virtualité implicite des fonctions

    Si une fonction doit voir son comportement modifié en fonction du type réel de l'objet au départ duquel elle est invoquée, (autrement dit : si une fonction a vocation à être redéfinie dans les classes dérivées), il faut indiquer explicitement au compilateur que la fonction est virtuelle.

    Ainsi, le constructeur de la classe Personnel doit etre virtuel, autrement, lorsqu'il sera appelé depuis un pointeur de type Personnel qui pointe en réalité sur un objet de type Employe, il ne fera le ménage que de la partie "Personnel" de l'employé, en "laissant trainer" tout ce qui est propre à la partie Employe

    De même, la fonction affiche doit aussi être déclarée virtuelle, autrement, le fait de l'avoir redéfinie dans la classe Employe "cachera" la fonction d'origine, laissant à penser que "tout va bien" lorsqu'elle est invoquée depuis (un pointeur ou une référence sur) un objet employé, mais n'affichera que les information propre au membre du personnel quand elle sera invoquée depuis (un pointeur ou une référence sur) un objet "passant pour etre du type Personnel"...

    Autrement dit, voici ce qui pourrait se passer. Nous pourrions avoir un code proche de:
    i
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    nt main()
    {
        Employe employe(/* paramètres requis */);
        Employe & refEmploye = employe;      // le cas d'une référence du type réel
        Employe * ptrEmploye = &employe;     // le cas d'un pointeur du type réel
        Personnel & refPersonnel = employe;  // on peut le faire : un employe est bien un membre du personnel
        Personnel * ptrPersonnel = &employe; // idem
        employe.affiche();                   // OK, affiche correctement les données de l'employe (voir sortie plus bas)
        refEmploye.affiche() ;               // OK, diem
        ptrEmploye->affiche();               // toujours pas de problème ;)
        refPersonnel.affiche();              // KO.. c'est la version de Personnel::affiche() qui est utilisée
        ptrPersonnel->affiche();             // KO idem
        return 0;
    }
    qui donnerait une sortie proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    NCI= 125Nom= DupontPrenom= Jeannb_h= 45tarif = 18.5
    NCI= 125Nom= DupontPrenom= Jeannb_h= 45tarif = 18.5
    NCI= 125Nom= DupontPrenom= Jeannb_h= 45tarif = 18.5
    NCI= 125Nom= DupontPrenom= Jean
    NCI= 125Nom= DupontPrenom= Jean
    M'est avis que tu aimerais, en travaillant avec un pointeur ou une référence de type Personnel, obtenir exactement la meme sortie que si tu avais travaillé avec l'objet de type Employe, non

    La solution est toute simple, modifions quelque peu la définition de la classe Personnel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Personnel
    {
        int NoCarteIdentite;
        std::string Nom;
        std::string Prenom;
        public:
        Personnel();
        Personnel(int nc, std::sttring const & nom, std::string const & prenom);
        virtual ~Personnel();
        virtual void affichage();
    };
    Et cela suffirait déjà, mais, à l'instar de beaucoup de mes collègues, je préfères répéter le mot clé virtal dans les classes dérivées (bien que la norme nous autorise à ne pas le faire ), simplemnt pour que le lecteur du code puisse se rendre compte qu'il s'agit d'une fonction destinée à être redéfinie sans devoir aller voir la classe parent

    Modifions donc la définition de la classe Employe (et de la classe Cadre) de la même manière
    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
    class Employe:public Personnel
    {
        float nb_h,tarif;
        public:
        Employe();
        Employe(int carteIdentite,std::string const & nom, 
                std::string const & prenom,float nh,float,tar);
        virtual ~Employe();
        virtual void affichage();
     
     
    };
    class Cadre:public Employe
    {
        float salaire,prime;
        public:
        Cadre();
        Cadre(int carteIdentite, const std::string const & nom,
             std::string const & prenom,float sal,float pri);
        virtual ~Cadre();
        virtual void affichage();
     
    };
    Et là, ca commence enfin à ressembler à quelque chose... Au moins, le programme réagira-t-il exactement comme on est en droit de s'y attendre

    Il ne te reste "plus qu'à" trouver le moyen de donner la responsabilité de la saisie à "autre chose" qu'aux classes (descendant de ) Personnel...

    La clé se trouve dans ce que l'on appelle un "desing pattern" nomme Fabrique (Factory en anglais )

    Mais, pour ne quand meme pas faire tout ton boulot, je vais te laisser chercher un peu
    Bonsoir,
    Il m'a fallu du temps pour lire ce que tu as écris Koala.En tant que débutante je n'ai compris que la moitié ; mais tu m'as incité à chercher plus loin pour mieux comprendre , je m'y mets sur le code pour le corriger

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

Discussions similaires

  1. Où l'erreur dans mon code
    Par moonia dans le forum Langage
    Réponses: 3
    Dernier message: 21/06/2006, 14h16
  2. Réponses: 5
    Dernier message: 14/05/2006, 22h41
  3. Erreur dans mon code PHP
    Par jack_1981 dans le forum Langage
    Réponses: 6
    Dernier message: 12/05/2006, 10h01
  4. erreur dans mon code
    Par sacco dans le forum C
    Réponses: 4
    Dernier message: 14/04/2006, 11h50
  5. [VBA][Débutant][export]erreurs dans mon code?
    Par Christophe93250 dans le forum Access
    Réponses: 4
    Dernier message: 06/01/2006, 19h52

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