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 :

problemes de classes dérivées


Sujet :

C++

  1. #1
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 417
    Par défaut problemes de classes dérivées
    Bonjour,

    J expose mon problème :

    J'ai deux classes Cplat et Cmenu.
    Cplat a 4 classes dérivées : Centrée Cviande Clegume Cdessert
    Cmenu a 2 classes dérivées : Cstandard Cenfant

    le constructeur de Cstandard est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    standard(string,Centrée,Cviande,Clegume,Cdessert)
    et celui de Cenfant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant(string,Centrée,Cdessert)
    Jusque là pas de problème.

    Pour des questions d'aisance, on veut stocker tous les plats dans un meme tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    vector<CPlat*> liste_des_plats;
    et on ajoute des plats dedans :
    liste_des_plats.push_back(new Cviande(...))
    liste_des_plats.push_back(new Centree(...))
    liste_des_plats.push_back(new Cdessert(...))
    ...
    toujours pas de problème (toutes les classes ont un constructeur sans argument et la méthode affiche de la classe mère est défini en virtuelle)
    on peut d'ailleurs utiliser les méthodes des classes dérivées

    par contre lorsque l'on veut définir un menu en appelant le constructeur comme suit, une erreur apparait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant test("menuenfant1",*liste_des_plats[1],*liste_des_plats[2]);
    Il attend en paramètre 2 et 3 respectivement :
    Centree et pas Cplat
    Cdessert et pas Cplat


    j'aimerais savoir s'il était possible de résoudre ce problème sans créér des tableaux différents pour chaque classe dérivée.
    Merci

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 094
    Billets dans le blog
    145
    Par défaut
    Bonjour,

    Je ne sais pas si je vais dire ce qu'il y a de mieux à faire, mais si tu veux vraiment faire ce que tu dis tu peux :
    Déclarer le constructeur comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant(string,Cplat*,Cplat*)
    Mais je comprend bien que tu veux obliger le codeur à passer un Centree et Cdessert
    L'autre possibilité c'est de faire un cast lors de l'appel du constructeur ( je pense que c'est encore pire comme solution mais je suis pas sur ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant test("menuenfant1",(Centree*)*liste_des_plats[1],(Cdessert)*liste_des_plats[2]);
    Par contre, je crois ( si ça compile O_o ) , le jour ou tu ne passe pas ce qu'il faut , ça plante ...

    Mais je me demande si il ne faut pas mettre des parenthèse ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant test("menuenfant1",*(liste_des_plats[1]),*(liste_des_plats[2]));
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

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

    Informations professionnelles :
    Activité : aucun

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

    Déjà, je ne suis pas particulièrement certain de l'opportunité d'avoir deux classe dérivées de CMenu...

    Finalement, qu'il s'agisse d'un menu enfant ou d'un menu "standard", il ne s'agit en réalité jamais que... d'un menu, et la distinction entre les deux peut n'être qu'un paramètre adapté...

    Au mieux, je verrais bien une énumération et une classe CMenu unique, 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
    enum eMenuType
    {
        mtStandard,
        mtEnfant
    };
    class CMenu
    {
        public:
            CMenu(eMenuType mt=mtStandard):mt(mt){}
            eMenuType menuType() const{return mt;}
        private:
            eMenuType mt;
    };
    Ensuite, un menu est une collection de plats, soit...

    Mais encore faut il réfléchir à ce que peut contenir cette collection de plats

    Plusieurs solutions s'offrent à toi:
    • Un menu est d'office composé d'une seule entrée, une seule viande, un seul type de légume et un seul dessert
    • Un menu peut être composé de plusieurs entrées, viandes, type de légumes et desserts
    • Un menu peut ne pas comprendre - par exemple - le dessert (ou l'entrée)
    • Dans l'ensemble des menus, on trouve le "mix" de toutes ces possibilités

    La manière dont on envisagera le menu dépendra des possibilités acceptées dans ton étude des besoins

    Et je ne suis pas forcément sur qu'il soit opportun de prévoir la création des entrées, viande, légumes et dessert dans le constructeur du menu...

    Il me semblerait plus opportun de n'indiquer que le fait qu'il s'agit d'un menu "standard" ou un menu enfant, dans le constructeur, puis de demander l'adjonction d'une entrée, d'une viande, d'un plat de légumes et d'un dessert, de manière séparée.

    En outre, je ne suis pas particulièrement certain de l'opportunité de faire dériver CEntree, CViande, CLegume et CDessert de plat...

    Bien sur, toutes ces classes ont des caractéristiques "communes" (le prix (éventuellement 2: un pour la version "standard", l'autre pour la version "enfant"), le nom et la description, éventuellement une photo ou un avis sur ce qu'on trouve dans l'assiette)... Mais le plat serait plutôt de mon point de vue la mise en commun de la viande et des légumes et ne devrait représenter que "le plat de consistance".

    Mais, si tu tiens à ta conception, peut être devrais tu te tourner vers un modèle proche du DP "factory".

    Tu aurais alors une fabrique de "plats", une fabrique de "menu", qui utilise la fabrique de plats, et la "carte" qui utilise la fabrique de menus, et qui les présente tous
    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

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 417
    Par défaut
    LittleWhite le cast ne marche pas, le tableau n arrive pas a convertir de CPlat a CEntree

    koala01, je ne peux pas modifier mes classes, la structure fait partie du cahier des charges et je ne peux pas faire autrement :/

  5. #5
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    La bonne solution dans ce cas, c'est le dynamic_cast.

    Plutôt que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant test("menuenfant1",*liste_des_plats[1],*liste_des_plats[2]);
    Tu écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Centree* entree = dynamic_cast<Centree*>(liste_des_plats[1]);
    Cdessert* dessert = dynamic_cast<Cdessert*>(liste_des_plats[2]);
    if(entree != NULL && desser != NULL)
    {
        Cenfant test("menuenfant1", entree, dessert);
        ...
    }
    else
    { // gérer cas d'erreur
    }

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 417
    Par défaut
    Nous avons un gagnant , merci beaucoup je vais pouvoir fonctionner avec un seul vector contenant plusieurs objets de classes différentes dérivés d'une meme classe.

    par contre l'appel du constructeur se fait par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cenfant test("menuenfant1", *entree, *dessert);
    encore merci

  7. #7
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Ça me fait penser que tu as peut-être un problème de durée de vie de tes objets.

    Dans ton vecteur, tu stockes des pointeurs.

    Dans ton constructeur, tu passes les paramètres par copie.

    Autrement dit, dans ton constructeur, tu as un objet temporaire. Si tu écris du code comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste_des_plats.push_back(&entree);
    Alors, une fois sorti de ton constructeur, l'objet entree n'existe plus, et dans liste_des_plats, tu n'as rien de bon.

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 417
    Par défaut
    quand j appelle le constructeur d'une de mes classes dérivées de plat je le fait comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste_des_plats.push_back(new CEntree(string,int,float,string));
    il alloue de la mémoire donc je pense qu il doit bien sauver mes objects

    pareil pour les classes dérivées de menus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste_des_menus.push_back(new CStandard(string,*(dynamic_cast<CEntree*>(liste_des_plats[0])),...,...,...));

    après je suis pas du tout expérimenté en c++

  9. #9
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Dans ce cas, si c'est liste_des_plats qui tient les ressources, et qu'elle existe tout le long de la durée de vie du programme, pas de problème.

    Par contre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new CStandard(string,*(dynamic_cast<CEntree*>(liste_des_plats[0])
    Suivant le code de CStandard, il peut y avoir problème ou pas. Si tu stockes une copie de l'objet CEntree, pas de problème. Si tu stockes un pointeur vers cet objet, problème.

    Sinon, dynamic_cast peut te renvoyer un pointeur NULL, si le cast échoue (par exemple, si liste_des_plats[0] n'est pas une entree, mais un dessert). Donc tu ne dois pas le déréférencer comme ça.

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    417
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2007
    Messages : 417
    Par défaut
    Suivant le code de CStandard, il peut y avoir problème ou pas. Si tu stockes une copie de l'objet CEntree, pas de problème. Si tu stockes un pointeur vers cet objet, problème.
    non non il stocke bien l'objet et pas un pointeur

    par exemple, si liste_des_plats[0] n'est pas une entree, mais un dessert :
    effectivement dans ce cas là ça plante, mais le programme est fait de telle sorte qu'il n y ait pas de problème de ce coté là mais c est vrai que tester le resultat du cast est plus prudent.

Discussions similaires

  1. Déterminer le type d'une class dérivée
    Par LDDL dans le forum MFC
    Réponses: 3
    Dernier message: 10/12/2004, 17h36
  2. Problème de "Class"
    Par Mr.KisS dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 01/10/2004, 23h23
  3. probleme compilation classe avec Borland c++ compiler 5.5
    Par softblue dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 17/06/2004, 15h16
  4. problème de classe d'association
    Par Nip dans le forum Diagrammes de Classes
    Réponses: 8
    Dernier message: 08/06/2004, 16h08
  5. Probleme de classe CComplex
    Par Balls dans le forum MFC
    Réponses: 7
    Dernier message: 13/02/2004, 10h55

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