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 :

Héritage et polymorphisme


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut Héritage et polymorphisme
    Bonjour, j'essaye actuellement de bien comprendre le polymorphisme et l'héritage, pour cela je veux résoudre un exercice type : les employés d'une entreprise.

    On souhaite gérer les différents employés d'une entreprise. Pour chacun on conserve son numéro de sécurité sociale et son nom. On souhaite également connaitre son emploi. L'entreprise a un patron, des vendeurs et des caissières. chaque employé, sauf le patron à un supérieur hiérarchique. Le patron touche son salaire ainsi qu'une prime de risque. Les vendeurs touchent une commission en plus de leur salaire. Les caissière touchent simplement leur salaire. Pour chaque employé on désir avoir les fonctions suivantes:
    - un constructeur
    - sePresenter qui permet d'écrire sur le terminal le numéro SS de l'employé, son nom et son emploi
    - revenu qui calcul le revenu de l'emplyé: salaire + prime ou commission s'il y a lieu
    -getsuperieur qui donne le supérieur hierarchique.

    Inclure une classe nommée CSS pour gérer le numéro de sécurité sociale.

    Concevez et programmez les différentes classes permettant de traiter le problème. Pensez au destructeurs et constructeurs de copie si besoin est. Aucune gestion d'erreur n'est demandée.

    Voila j'ai à peu près modéliser le problème comme suite :

    class employé :
    - CSS secu
    - string nom
    - string emploi
    +employe() constructeur
    +sePresenter() Virtuel pure donc classe abstraite
    +revenu() virtuel pure
    + getsuperieur() virtuel pure
    ~employe() destructeur virtuel

    class patron:
    - double salaire
    - double prime
    +patron()
    +sePresenter()
    +revenu()
    +getsuperieur
    ~patron()

    class vendeur:
    - double salaire
    - double commission
    +vendeur()
    +sePresenter()
    +revenu()
    +getsuperieur
    ~vendeur()

    class caissiere:
    - double salaire
    +caissiere()
    +sePresenter()
    +revenu()
    +getsuperieur
    ~caissiere()

    Voila j'ai ainsi pu programmer les différentes classes. Mais il reste quelque chose qui me taquine. En effet, le salaire étant présent dans les trois sous-classes, je me demande s'il n'était pas plus judicieux de l'envoyer dans la classe employé .

    Si quelqu'un peut m’éclaircir sur ce point ce serait cool.

    Merci

  2. #2
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Il paraîtrait logique de le mettre dans la classe mère pour que les classes l'ait directement. Ça évitera d'avoir à le refaire dans chaque classe. Tu aurais pu faire une classe abstraite au lieu d'une interface pour la classe mère, ça t'aurais éviter d'avoir à redéfinir les fonctions dans chaque classe fille car je présume que le code pour getSuperieur doit être le même à chaque fois...

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut
    Merci pour la réponse rapide . J'avais un doute parce que dans un livre, j'ai trouvé un exercice similaire mais il mettait le salaire dans les sous classes sous prétexte qu'il en avait besoin pour calculer le revenu, bref ça m'a parut bizarre.

    Sinon pour le constructeur de copie, comment savoir s'il y en a besoin ou pas ? D'après ce que j'ai compris, dès qu'il y a des pointeurs il faut penser au constructeur de copie. Ce qui me fait penser qu'on en a besoin surtout pour la classe mère ( employé) , je me trompe ?

  4. #4
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    Un bon exemple de constructeur par copie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    std::string s1 = "tralala"; // surcharge de l'opérateur égal
     
    std::string s2(s1); // constructeur par copie
    std::string s3 = s2; // surcharge de l'opérateur égal
    Donc après à toi de voir si dans ton code tu en as besoin. Dans le cas de ton programme, je ne vois pas trop l'intérêt étant donné que chaque personne est unique (il me semble). Dire nouveau venu = george ne me semble guère utile. Après rien ne t'empêches de surcharger une fonction de classe mère (n'oublies pas de la mettre virtual dans ce cas-là) dans une classe fille si son fonctionnement diffère.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut
    Merci beaucoup j'ai compris l'idée en ce qui concerne les constructeur de recopie.

    Donc pour l'héritage c'est vraiment strict : chaque attribut qui se répète dans les sous classes doit être factorisé dans la classe de base.

    Merci, je vais pouvoir programmer mes classes sans hésitation.

    Bonne journée

  6. #6
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    C'est pas une obligation, c'est juste pour éviter d'avoir à répéter sans cesse le même code qu'on le fait (et ça fait aussi partie du principe de l'héritage).

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut
    Oui, je comprend que c'est pas une obligation, mais dans un exercice comme ça, ça montre qu'on a compris le concept quoi

  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
    Citation Envoyé par gbsatti Voir le message
    Voila j'ai ainsi pu programmer les différentes classes. Mais il reste quelque chose qui me taquine. En effet, le salaire étant présent dans les trois sous-classes, je me demande s'il n'était pas plus judicieux de l'envoyer dans la classe employé .
    Citation Envoyé par imperio Voir le message
    Il paraîtrait logique de le mettre dans la classe mère pour que les classes l'ait directement. Ça évitera d'avoir à le refaire dans chaque classe. Tu aurais pu faire une classe abstraite au lieu d'une interface pour la classe mère, ça t'aurais éviter d'avoir à redéfinir les fonctions dans chaque classe fille car je présume que le code pour getSuperieur doit être le même à chaque fois...
    Citation Envoyé par gbsatti Voir le message
    Merci pour la réponse rapide . J'avais un doute parce que dans un livre, j'ai trouvé un exercice similaire mais il mettait le salaire dans les sous classes sous prétexte qu'il en avait besoin pour calculer le revenu, bref ça m'a parut bizarre.
    En fait, si tu parles du salaire de base qui est commun (hors variation sur le montant, s'entend ) à toutes les classes, il est, en effet, logique de le placer dans la classe de base, car on peut estimer qu'il s'agit d'une information majeure propre à la classe "employé"
    Sinon pour le constructeur de copie, comment savoir s'il y en a besoin ou pas ? D'après ce que j'ai compris, dès qu'il y a des pointeurs il faut penser au constructeur de copie. Ce qui me fait penser qu'on en a besoin surtout pour la classe mère ( employé) , je me trompe ?
    En fait, il faut s'intéresser à la sémantique des classes que tu définis :

    Il existe deux grands "groupes" de classes en fonction de la sémantique qu'elles ont :

    Les classes à sémantique de valeur, dont il est possible d'avoir, à un instant T, plusieurs instances en mémoire présentant exactement les même valeurs.

    C'est le cas, par exemple, des classes "couleurs", "point", "réservoir à essence", "adresse", etc. Bref, tout ce qui peut exister en plusieurs exemplaires scrupuleusement identiques.

    Ces classes sont, généralement:
    • constantes : si tu modifies une des valeurs qui les représente, tu obtiens un objet totalement différent
    • copiable : tu peux souhaiter avoir un couleur qui est la même que celle du voisin
    • assignable : tu peux décider de repeindre une pièce dans une autre couleur que celle d'origine
    • comparables (au minimum par égalité)
    • peu encline à intervenir dans une relation d'héritage (ni en tant que classe de base, ni en tant que classe dérivée)
    C'est à ce genre de classe que Coplien fait référence dans sa fameuse forme canonique orthodoxe, et c'est à ce genre de classe que s'applique la fameuse "règle des trois grands":

    Si, parmi les trois fonctions importantes que sont le constructeur par copie, l'opérateur d'affectation et le destructeur, il y en a une dont le comportement doit être définis (comprend : dont tu ne peux pas te contenter d'utiliser le comportement par défaut implémenté par le compilateur), alors, il faudra envisager de définir les trois

    Ensuite, il y a les classes ayant sémantique d'entité, dont chaque instance est identifiée de manière unique et non ambigüe.

    C'est le cas de classes comme "personne", "véhicule", "compte bancaire". Bref, toutes les classes pour lesquelles chaque instance doit être scrupuleusement unique pour avoir la certitude que si tu modifie une des données (parmi celles qui peuvent être modifiées) d'une instance quelconque, la modification s'applique effectivement à cette instance particulière.

    Ces classes sont généralement
    • modifiables (du moins, pour tout ce qui n'intervient pas dans la définition de ce qui permet de les identifier de manière unique et non ambigüe)
    • non copiable : tu n'apprécierais pas trop que quelqu'un ait un compte en banque portant le même numéro que le tien et que ton salaire soit versé... sur le compte de cette personne
    • non assignable, pour la même raison
    • non comparable : au pire, on peut comparer les différentes valeurs qui les composent une à une, mais il n'y a aucun sens à comparer l'intégralité
    • des candidats idéaux à intervenir dans une relation d'héritage (soit comme classe de base, soit comme classe dérivée)
    Pour ce type de classes, il y a généralement lieu de faire en sorte que les constructeur par copie et l'opérateur d'affectation soient inaccessibles.

    En C++ (avant la nouvelle norme), cela se traduisait souvent par le fait de déclarer le constructeur par copie et l'opérateur d'affectation comme étant privés sans les définir.

    En C++11, il est possible de simplement les déclarer comme "deleted", sous une forme proche de
    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
    class MyBaseClass
    {
        public:
            /* un constructeur "classique" */
            MyBaseClass(/* ...*/ );
            /* le constructeur par copie que l'on annule */
            MyBaseClass(MyBaseClass const &) = delete;
            /* l'opérateur d'affectation que l'on annule aussi */
            MyBaseClass & operator=(MyBaseClass const &) = delete;
            /* le destructeur se doit d'être virtuel, pour permettre
             * la destruction des objets dérivés (ou d'être non virtuel et 
             * protégé)
             */
            virtual ~MyBaseClass();
    };
    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 à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut
    Merci pour l'explication vraiment bien détaillée , je pense avoir bien compris l'idée.

    Sinon que veux-tu dire par "hors variation du montant" ? Car d'après l'énoncé, je pense que le salaire peut varier en fonction en fonction de chaque employé ( il peut paraître logique que le salaire du patron ne soit pas le même que celui de la caissière par exemple)

  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 gbsatti Voir le message
    Sinon que veux-tu dire par "hors variation du montant" ? Car d'après l'énoncé, je pense que le salaire peut varier en fonction en fonction de chaque employé ( il peut paraître logique que le salaire du patron ne soit pas le même que celui de la caissière par exemple)
    C'est exactement ce que je voulais dire : c'est une donnée commune, mais le montant du salaire peut varier d'un type d'employé à l'autre.

    Il faudra donc prévoir de fournir cette information au niveau du constructeur de la classe mère, et voir s'il est plus cohérent de le fixer au niveau du constructeur des classes dérivées ou, au contraire, de permettre de le définir séparément pour chaque employé

    Il serait d'ailleurs tout à fait envisageable d'avoir une optique différente en fonction du type d'employé, en offrant un salaire fixe aux caissières, mais en permettant de définir le salaire des vendeurs et du patron, par exemple
    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
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par imperio Voir le message
    Un bon exemple de constructeur par copie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::string s3 = s2; // surcharge de l'opérateur égal
    Non, c'est là aussi le constructeur de copie qui est utilisé, cette ligne est équivalente à
    Pour utiliser la surcharge de l'opérateur =, il faudrait écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::string s3;
    s3 = s2;

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut
    Ok je vois ce que tu veux dire, donc si par exemple je veux fixer le salaire des caissières à 1300€ par exemple. Je dois appeler le constructeur de la classe mère en initialisant le salaire à 1300.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    employe(CSS s, string n,string e, double s)
    { 
        secu=s;
        nom=n;
        emploi=e;
        salaire=s;
    }
     
    caissiere(CSS s, string nom, string emploi, double salaire, double p)
    {
        employe(s,n,"caissiere",1300)
        prime=p;
    }
    c'est ça ?

  13. #13
    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
    A peu de choses près, les erreurs en moins, oui, c'est ca

    En fait, cela ressemblerait à quelque chose comme
    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
    class Employe
    {
        public:
            Employé( CSS const & secu, std::string const & nom,
                           std::string const & prenom, double salaire):
                           secu_(secu), nom_(name), prenom_(firstName),
                           salaire_(salaire){}
             virtual ~Employe();
             /* tout le reste */
        private:
            CSS secu_;
            std::string nom_;
            std::string prenom_;
            double salaire_;
    };
    class Caissiere : public Employe
    {
        public:
            /* pour les caissières, le salaire est fixé arbitrairement à 1500,00€ */
            Caissiere(CSS const & secu, std::string const & nom,
                          std::string const & prenom): Employe(nom, prenom, 1500.0){}
            /* ce qui est propre aux caissières */
    };
    class Vendeur : public Employe
    {
        public:
            /* pour les vendeurs (comme pour le patron), le salaire est le 
             * fruit d'âpres négociations ;)
             */
            Vendeur(CSS const & secu, std::string const & nom
                         std::string const & prenom, double salaire)
                         Vendeur(secu, nom, prenom, salaire){}
            /* ce qui est propre aux vendeurs */
    };
    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

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 47
    Points : 22
    Points
    22
    Par défaut
    Merci, j'ai vu mon erreur, en fait il ne faut pas passer le salaire en paramètre pour les caissières si je veux le "forcer" à 1300. C'est un peu comme l'emploi dans les sous classes patron,vendeur et caissière. Si j'ai bien compris, il faut en quelque sort cacher l'opération de sorte à ce qu'on ne puisse plus le redéfinir, et ce pour chaque nouvelle caissière.

    Merci en tout cas ton aide m'a été précieuse.

    Je met en résolu.

    Bonne journée

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

Discussions similaires

  1. héritage et polymorphisme
    Par julien.metais dans le forum Hibernate
    Réponses: 3
    Dernier message: 17/05/2009, 09h58
  2. Réponses: 10
    Dernier message: 17/07/2008, 20h01
  3. héritage et polymorphisme
    Par davdou dans le forum JSF
    Réponses: 2
    Dernier message: 23/11/2007, 09h51
  4. [C#] Information sur héritage et polymorphisme
    Par LE NEINDRE dans le forum C#
    Réponses: 21
    Dernier message: 14/06/2007, 11h00
  5. Réponses: 19
    Dernier message: 05/06/2007, 08h13

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