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

Langage C++ Discussion :

Héritage : Passage d'une classe mere à une classe fille


Sujet :

Langage C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut Héritage : Passage d'une classe mere à une classe fille
    Bonjour à tous,

    Je suis entrain de créer un petit logiciel sur Qt Creator, et je bloque un peu sur une histoire de classe fille héritant d'une classe mere...

    Ma logique me paraissait censée au départ, mais maintenant, je me demande si je peux réellement faire ce que je souhaite...

    Je m'explique :

    J'ai une classe mère fruit qui ne contient pas grand chose, et deux classes filles (pomme et banane) héritant de la classe fruit.

    Dans le code de mon application, j'ai un tableau de fruit, dans lequel je souhaite pouvoir stocket soit des pommes soit des bananes... Ca fonctionne bien car comme les 2 sont hérités de la classe fruit, pas de problème!

    Par contre, plus loin dans mon code j'utilise ce tableau de fruit, je le parcours et je souhaite pouvoir traiter chaque élement comme une pomme ou une banane, mais mon compilateur ne voit mes objets que comme des fruits (donc pas d'accès aux attributs et fonctions particuliers à la pomme et a la banane...), alors qu'au départ il s'agissait bien de pomme et de banane...

    Enfin voila mon problème Est-ce que ma logique est bonne, ou est-ce qu'il est impossible de faire ce que je fais ? (il faut passer par un cast ou quelque chose dans le style ?)

    Merci d'avance pour vos réponses et les éventuelles pistes que vous pourrez me donner.

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    Ne peux-tu pas te contenter du polymorphisme ?
    En déclarant virtual les fonctions de l'interface fruit, lors du parcours de ton tableau ce sont les fonctions du vrai type qui seront appelées.

    Sinon oui il te faut réaliser un cast (dynamic ou static si je ne me trompe), mais tu perds tout l'intérêt de l'héritage et surtout : comment tu sais si tu as une banane ou une pomme quand tu parse un fruit du tableau ?
    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 du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut
    Merci pour ta réponse,

    En fait dans ma classe fruit, j'avais ajouté un attribut de type (afin de savoir si le fruit était une banane ou une pomme), c'est avec cet attribut que je comptais savoir quel type de fruit j'avais a traiter...

    Mais je pense que tu as probablement raison, je vais essayer de partir sur du polymorphisme... Par contre a ce sujet, encore une petite question...

    Si lors du parcours de mon tableau j'arrive à
    mon_fruit.attribut_pomme

    Est ce que je peux accéder à mon attribut de cette manière (si on part du principe que mon_fruit est une pomme et que attribut_pomme est déclaré en public) ou est-ce qu'il faut forcément que je passe par une fonction virtuelle dans la classe fruit (du genre virtual fruit::getAttributPomme(), et qui du coup n'aura plus de sens dans le cas d'une banane) ?

  4. #4
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Tu te focalises trop sur la pomme ou la banane.
    Il faut rester en vu d'un fruit, quelconque.

    http://apais.developpez.com/tutoriel...ge_5#LXXII-B-4
    http://apais.developpez.com/tutoriel...age=page_1#LIV

    hésite pas à fournir un peu de code.
    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 émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Dans ton panier de fruit, stocke des pointeurs vers tes fruits, et utilise le polymorphisme.

    Si tu veux vraiment stocker des objets, il faut passer par Boost.Any.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut
    Voila un peu de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class fruit
    {
    public:
        fruit();
        // Attributs
        QString type_fruit; // 1=>pomme, 2=>banane
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class pomme : public fruit
    {
    public:
        pomme();
        // Attributs
        int att_pomme_1;
        int att_pomme_2;
        int att_pomme_3;
        int att_pomme_4;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class banane : public fruit
    {
    public:
        banane();
        // Attributs
        int att_banane_1;
        int att_banane_2;
        int att_banane_3;
        int att_banane_4;
    };
    Ensuite, voila le code que je peux retrouver dans mon main

    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
     
    QVector<fruit> panier_fruit;
    [---]
    pomme unePomme = new pomme();
    banane uneBanane = new banane();
    // Remplissage des attributs particuliers aux deux fruits
    [---]
    panier_fruit.append(unePomme);
    panier_fruit.append(uneBanane);
     
    [---]
     
    int nb = panier_fruit.count();
    for(int i=0; i<nb; i++) {
     
    fruit temp_fruit = panier_fruit.at(i);
    if (temp_fruit.type_fruit=="pomme") {
       my_var_pomme = temp_fruit.att_pomme_1;
       my_var_pomme_2 = temp_fruit.att_pomme_2;
    } else {
       my_var_banane = temp_fruit.att_banane_1;
       my_var_banane_2 = temp_fruit.att_banane_2;
    }
     
    }
    Voila ça ressemble a peu près à ça (ce n'est pas le code exact, car je nel'ai pas sous la main pour l'instant, mais c'est exactement ça dans l'idée).

    Et donc c'est la partie d'affectation qui évidemment ne marche pas (par ex : my_var_pomme = temp_fruit.att_pomme_1 ou mon compilateur me dit naturellement que att_pomme_1 n'est pas un attribut de fruit...

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    La question: qu'est-ce que les fruits ont en commun qui pourrait être utilisé sans savoir si on a une pomme ou une banane, mais avec un résultat différent pour la pomme ou la banane?
    Ex: getCouleur():Couleur retournerait une Couleur rouge ou verte pour une pomme, une Couleur systématiquement jaune pour une banane.
    Si ta réponse à la question est: rien, pomme et banane sont des fruits mais je les utilise complètement différemment, alors ton héritage n'a pas de sens...

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Je dirais plutôt qu'il a du sens, mais pas d'utilité (mais rien n'exclut qu'il puisse en avoir une par la suite).

  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    gui38 :

    Soit tu passes par des fonctions virtuelles, soit par un conteneur hétérogène (mais bof).

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut
    Oui c'est un peu ça... pour l'instant ça n'a pas d'utilité... mais en fait, je veux pouvoir rajouter par exemple d'autres types de fruits sans avoir a modifié le coeur de mon code (vu qu'au final j'aurais toujours un Vecteur de fruit, meme si je rajoute des peches et des fraises).

    Je pense qu'en passant par des pointeurs et du polymorphisme ça devrait passer, mais du coup ce que je ne vois pas c'est les fonctions virtuelles que je dois ajouter à ma classe fruit (a moins que je puisse accéder directement à mes attributs si ceux-ci sont déclarés en publics ?)...

    Par exemple, il faut que je fasse un getPommeAttribut1, un getBananeAttribut1, un getPommeAttribut2, un getBananeAttribut2 etc... ?

    Je ne trouve pas ça super utile...

    Peut-être que je peux faire un getAttribut en Virtuel, et je retourne l'objet concerné dans les fonctions de la classe fille (par ex : return this), mais je ne sais pas ci c'est bien clean...

  11. #11
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Tu prends le problème par le mauvais bout. Que veux tu FAIRE de tes fruits? Encore une fois si tu les utilises différemment les un des autres, fais une collection par type, ce ne sera pas plus compliqué...et ce sera plus facile à lire.

  12. #12
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    je veux pouvoir rajouter par exemple d'autres types de fruits sans avoir a modifié le coeur de mon code (vu qu'au final j'aurais toujours un Vecteur de fruit, meme si je rajoute des peches et des fraises).
    Et c'est exactement l'inverse que tu t’apprêtais à faire.
    A chaque ajout de fruit, tu aurais du remodifier le code du parcours en ajoutant le nouveau type, son if, les cast, ...

    Par exemple, il faut que je fasse un getPommeAttribut1, un getBananeAttribut1, un getPommeAttribut2, un getBananeAttribut2 etc... ?
    Pas du tout.
    Ne vois-tu pas un cas flagrant de factorisation ?
    Le simple fait que tu aies besoin d'un getAttribut1..n pour chaque fruit indique que c'est une spécificité de Fruit et non de chacun d'eux.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Par ailleurs, histoire que la botanique vienne perturber tout ça, les pommes, poires, bananes, et fraises ne sont pas vraiment des fruits.

  14. #14
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Et c'est exactement l'inverse que tu t’apprêtais à faire.
    A chaque ajout de fruit, tu aurais du remodifier le code du parcours en ajoutant le nouveau type, son if, les cast, ...


    Pas du tout.
    Ne vois-tu pas un cas flagrant de factorisation ?
    Le simple fait que tu aies besoin d'un getAttribut1..n pour chaque fruit indique que c'est une spécificité de Fruit et non de chacun d'eux.
    ++
    Et en admettant que tu aies besoin de récupérer ces attributs sans savoir quel est le fruit, je suggérerais:
    attributeCount():int
    attribut(int n):Attribut

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut
    Eh eh, en effet ;-)

    En fait je parle de fruit pour m'imager le truc, en réalité je travaille sur des composants industriels, mais c'est plus facile de comprendre sur des exemples simples (pour moi en tout cas), j'aurais pu prendre aussi un garage de véhicules, avec des motos et des voitures, ça aurait été pas mal.

    Pour en revenir au sujet, en fait, oui je changerais mon code, mais juste une nouvelle condition dans ma boucle, le coeur resterait le même (je stocke un vecteur de fruit), si je décide d'en rajouter un nouveau, je rajoute juste la condition qui va bien.

    Pour l'instant c'est vrai que je n'ai pas beaucoup d'attributs en commun, mais a terme je ferais un petit ménage pour mettre tout ça comme il faut... Mais peut-être que tu as raison, je me prends la tête sur quelque chose qui n'a pas lieu d'être, même si pour moi ça me parait logique de fonctionner comme ça (fruit > pomme | fruit > banane etc...).

    Je pense que je ferais le test avec une fonction virtuelle getAttribut qui me retournerait le this dans les classes filles (mais la encore, qu'est ce que je met comme type de retour de lafonction au niveau de la classe mere )... comme ça je devrais bien me retrouver avec le bon objet. Puis si ça ne marche pas, je ferais simplement des classes séparées, et j'abandonnerais cette idée de panier de fruit (qui n'en sont pas ;-) )

  16. #16
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Retourner le this, mais pour quoi faire? Si tu peux appeler la méthode, c'est que tu as déjà un pointeur ou une référence...
    La question, reste, que fais tu de tes composants. Grouper des composants juste parce que ton programme les manipule n'a pas de sens.
    La question est: quel service offre chacun de tes types d'objets. Si certains de ces services sont essentiellement communs (c'est à dire qu'on fait le même type de calcul, donnant le même type de résultat mais avec une "méthode de calcul" différente pour chaque sous-type) alors ça vaut le coup de monter un héritage. Sinon, ça ne fera que créer une usine à gaz...

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut
    Oui a terme je l'imagine comme ça... Il y aura des services communs mais avec des méthodes de calculs différents...

    Le problème c'est qu'actuellement, j'en suis qu'au début, c'est a dire que pour l'instant j'ai un panier_fruit, j'ai une methode pour ajouter des éléments sur dans ce panier et ensuite, je veux juste pouvoir afficher aux bon endroits les infos si on a tel ou tel fruit...

    Je voulais en fait simplement partir sur une structure assez souple pour plus tard... je suis donc parti sur un texte rédigé "en français" pour définir les structures (du type : "J'ai un ensemble de machine. Une machine peut-être une machine_XXX ou une machine_YYY etc...). Mais je me retrouve bloqué au moment de retrouver la bonne machine_XXX ou machine_YYY que j'avais mise dans mon tableau

    Mais peut-être que je fais totalement fausse route dans ma démarche (c'est pas impossible )

  18. #18
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Disons que dans un premier temps si tu n'affiches qu'une sorte d'inventaire, tu pourrais partir sur quelques attributs communs:
    ->type
    ->marque/modèle
    ->n° de série
    (comme quoi raisonner trop dans le vide...)
    puis ce que je tu suggérais tout à l'heure:
    listerAttributsSpecifiques():std::vector<Attribut>
    où Attribut:
    nom():std::string
    valeur():std::string
    EDIT: notes cependant que ce point commun pourrait aussi être factorisé par délégation: toutes tes machines pourraient avoir un attribut de type Descriptif reprenant ce que j'ai décrit plus haut.

  19. #19
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par gui38 Voir le message
    Mais je me retrouve bloqué au moment de retrouver la bonne machine_XXX ou machine_YYY que j'avais mise dans mon tableau
    C'est parce que tu te poses des questions inutiles.
    On s'en moque de savoir si la machine est une machine_XXX ou une machine_YYY ou une machine_ZZZ dont on a pas encore connaissance qui serait susceptible d'arriver.

    Tout ce qui nous intéresse c'est qu'une machine puisse être Start ou Stop par exemple, après chacun en fait ce qu'elle veut. Et on laisse faire le polymorphisme.

    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
    class CMachine
    {
    public:
      virtual void Start()=0;
      virtual void Stop()=0;
    };
    class CMachine_XXX : public CMachine
    {
    public:
      virtual void Start() { cout<<"start machine_xxx"<<endl; }
      virtual void Stop() { cout<<"stop machine_xxx"<<endl; }
    };
    class CMachine_YYY : public CMachine
    {
    public:
      virtual void Start() { cout<<"start machine_yyy"<<endl; }
      virtual void Stop() { cout<<"stop machine_yyy"<<endl; }
    };
    class CMachine_XXXXX2 : public CMachine
    {
    public:
      virtual void Start() { cout<<"start machine_xxxxx2"<<endl; }
      virtual void Stop() { cout<<"stop machine_xxxxx2"<<endl; }
    };
    vector<CMachine*> vecMachines;
    vecMachines.push_back(new CMachine_XXX);
    vecMachines.push_back(new CMachine_YYY);
    vecMachines.push_back(new CMachine_XXXXX2);
    for(int i = 0; i < vecMachines.size(); ++i)
    {
      vecMachines[i]->Start();
      vecMachines[i]->Stop();
    }
    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.

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 117
    Points : 54
    Points
    54
    Par défaut
    Oki, merci pour vos conseils

    Je vais essayer de voir comment m'organiser avec les fonctions virtuels pour arriver a faire ce que je veux.

    EDIT : Bon ça roule comme ça, avec le polymorphisme et des fonctions get abstraite pour retourner les paramètres comme il faut! Merci la communauté

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 08/07/2014, 18h41
  2. [XL-2002] Macro de comparaison d'une cellule d'une feuille avec une cellule d'une autre feuille.
    Par steelydan dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 08/09/2010, 12h59
  3. Réponses: 4
    Dernier message: 15/10/2009, 13h33
  4. [XL-2007] Afficher une checkbox dans une feuille si une checkbox d'une autre feuille est cochée
    Par JessieCoutas dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 18/08/2009, 13h35
  5. Recherche une valeur d'une cellule dans une colonne d'une autre feuille
    Par kourria dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/06/2007, 13h48

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