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 tableau d'objets


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Par défaut Héritage et tableau d'objets
    Bnojour à tou(te)s,

    Suite à mon post de ce matin (Héritage et constructeur par copie) j'ai un nouveau souci
    J'ai maintenant un tableau qui contient tout un tas d'objets qui héritent tous d'une même classe ou d'une sous-classe, etc...

    J'ai créé une fonction GetElementByName afin de récupérer un élément de mon tableau. Le problème (encore) c'est qu'il me récupère un cBase* (cBase est ma classe de base donc) et n'a donc pas connaissance des méthodes des classes dérivées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    cBase * GetElementByName (std::string Name)
    {
    // Création d'un itérateur sur mon tableau, donc un itérateur de cBase*
    // Recherche
    // Retour d'un cBase* donc...
    }
    Comment je fais pour pouvoir retourner la bonne classe ?

    Merci encore pour votre patience !

  2. #2
    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
    Si tu dois retrouver le type réel d'un objet qui se trouve dans une collection d'objets du type de base, c'est qu'il y a - quelque part - une problème de conception...

    Ceci dit, il existe plusieurs solutions pour - éventuellement - décider le type dérivé dans lequel il faut "downcaster" le type de base, afin d'être en mesure d'accéder à une méthode particulière... Mais ce n'est généralement par recommandé
    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

  3. #3
    Membre éclairé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Par défaut
    Ah ah ! Tu m'intéresses !
    Un problème de conception ? Alors je t'explique mon idée :

    J'ai une classe principale Vehicule
    Je crée d'autres classes Voiture, Camion, etc...
    Je crée des sous-classes de Voiture (Berline, Sport, etc...) et de Camion, etc...
    etc...

    Maintenant, je veux pouvoir gérer aussi bien de simples voitures que des berlines, des camions, etc... J'ai donc créé une classe pour gérer ca et qui contient un tableau de Vehicule*
    Ca me permet donc de placer dedans aussi bien des Berline que des Camion, ok ?

    Maintenant, lors de l'utilisation de mon appli, je veux pouvoir dire que ma Berline qui s'appelle "1234 XY 98" (la plaque c'est son identifiant) je veux lui faire faire quelque chose de particulier. J'ai donc penser à une fonction GetElementByName qui me permet de retrouver cet objet précisément et donc de pouvoir l'utiliser. Un peu comme en DOM dans le web :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (machin)
    {
     MonManager.GetElementByName("1234 XY 98")->MethodeSpecifiqueBerline();
    }
    C'est pas possible ca ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    MonManager.GetElementByName("1234 XY 98") retournera a priori un Vehicule et non une Berline.
    En effet, il est fort possible que cette plaque soit celle d'un autre type de véhicule.

  5. #5
    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
    Ce qui m'intéresserait de savoir c'est, dans quel cas il est important de pouvoir appeler une méthode spécifique aux berlines sur un objet spécifique d'une collection de véhicule

    N'oublie jamais que, bien souvent, si une classe a plus d'une responsabilité, c'est qu'elle en a sans doute trop

    Si, quelque part, tu a décidé de faire passer n'importe quel type de véhicule pour... un véhicule, c'est que tu estimais que tu pouvais tous les gérer comme tel (les camion, les voitures, les vélos, les patins à roulettes ...)

    Cela signifie que, si tu dois pouvoir gérer différemment les différents types de véhicule, c'est qu'il te faut une classe pour gérer chaque type distinctement, quitte à prévoir une classe qui traite les véhicules de manière plus générique (et sans doute une information permettant, sur base d'un véhicule générique, de savoir de quel type de véhicule il s'agit réellement)

    N'oublie pas non plus que, finalement, qu'il s'agisse d'une berline, d'une voiture de sport ou d'un "mono space", tu ne fais que modifier les caractéristique de la voiture, mais que ca reste... une voiture

    Je dirais presque que le fait qu'une voiture soit une berline, d'un modèle "sport", un monospace ou ... ne fait que représenter un état particulier du véhicule reconnu comme "voiture"

    Tu en viendrais presque à devoir envisager une logique du genre 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
    16
    si (LeVehicule est un camion)
    {
        demander à GestionnaireCamion de me donner le camion (identité)
        travailler sur le camion reçu
    }
    sinon si (LeVehicule est une voiture)
    {
        demander à GestionnaireVoiture de me donner la voiture (identité)
        travailler sur la voiture reçue
    }
    sinon si (LeVehicule est un char à voile)
    {
        demander à GestionnaireCharAVoile de me donner le char à voile (identité)
        travailler sur le char à voile reçu
    }
    ...
    Un joli mélange du pattern "mediator" et du pattern "chain of responsability" serait de nature à te permettre ce genre de chose

    EDIT la précision qui peut manquer:

    Le pattern "mediator" sera de nature à permettre à tous les gestionnaires particuliers de discuter avec le gestionnaire générique (et inversément) et le pattern "chain of responsability" serait de nature à permettre au gestionnaire générique de manipuler tous les véhicules particuliers
    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

  6. #6
    Membre éclairé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Par défaut
    Bon, je comprends un peu.
    En même temps c'est pour des tests que j'ai besoin d'un tel accesseur pour le moment, donc pas hyper important.

    Je marque résolu, et je reviendrai voir ca après les fêtes voir si je comprends mieux

    Merci !

  7. #7
    Membre éclairé
    Avatar de Kalite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 310
    Par défaut
    Salut

    Comme la dit koala01 tu a un problème de conception certain. Après je ne connai pas les deux patern qu'il a citer. Moi je t'aurai plutot aiguillé sur un patern "visiteur".

    Tu trouvera tous ce que tu a besoin concernant les paterns sur le net.

    Salut.

  8. #8
    Membre éclairé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Par défaut
    Me revoilà, après les fêtes !
    Merci pour vos réponses, et moi je vois que mon explication est bien male faite. Dans mon cas, je fais une GUI. Dans ce cas là, tous mes objets se basent sur ma base virtuelle "conteneur".

    Lorsque, dans mon "main", je veux lancer une fonction (suite à l'appui d'une touche par exemple) d'un objet en particulier, je souhaitais pouvoir faire cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Root.GetElementByName("Bouton_1").SetText("Clique-zmoi");
    Je suis désolé de vous avoir déporté vers le sujet "voitures" ce qui n'était peut-être pas la meilleure idée pour me faire bien aider

    Donc, voilà. Mon objet "Root" est un objet un peu particulier qui contient un tableau de pointeurs type cBase* et je voudrais bien accéder à mes éléments une fois insérés dans le tableau

    Merci beaucoup d'avance de vos idées/opinions/critiques/etc...

  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
    Classiquement, dans ces cas-là, on stocke une propriété sur l'objet, qui donne le type réel de l'instance. Ensuite, on teste cette propriété et on caste en fonction. C'est ce que fait DOM, notamment.

    Sinon, tu peux aussi utiliser des interfaces (le problème sera le même, mais ça limite les cas particuliers), par exemple, dans ton cas, tu pourrais avoir une interface ControlWithText, qui définit des méthodes virtuelles pures GetText et SetText, et un moyen de tester si un objet CBase* implémente l'interafce ControlWithText (par exemple, une fonction membre). En passant par des smart pointers, tu peux en plus jouer sur l'opérateur de cast et de comparaison à NULL (méthode COM), et faire des choses du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CControlWithTextPtr ctrlText = static_cast<CControlWithTextPtr>(ctrl);
    if(ctrlText != NULL)
    {
       ...
    }
    L'autre solution, la plus mauvaise à mon avis, consiste à mettre dans la classe de base l'ensemble des méthodes possibles, même si elles n'ont pas de sens sur l'objet. Cette méthode est très répandue, et c'est à mon avis la pire. À éviter.

    Contrairement à ce que d'autres ont dit, je ne pense pas que ça témoigne nécessairement d'un problème de conception. Il y a des cas (typiquement, arbre d'interprétation d'un langage, gui...) où l'on a besoin de collections d'objets faiblement typés, et l'on a besoin d'un traitement particulier suivant le type réel de l'objet. Cela dit, je regarde de plus en plus du côté de boost::any pour ce genre de cas (plus extensible, je pense).

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    N'est-ce pas plutôt un dynamic_cast que tu voulais montrer?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    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
    Effectivement... J'ai un peu trop pensé à COM et un peu oublié dynamic_cast quand j'ai écrit mon message. Les smart pointers de COM simulent le comportement du dynamic_cast, mais avec des cast statiques.

    Cela dit, dynamic_cast ne permet pas à ma connaissance de faire un cast en une interface non dérivée du type de base. Donc dans le cas d'un objet implémentant plusieurs interfaces, ce n'est inutilisable (au contraire de l'opérateur as de C#, qui pour le coup est bien pratique).

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Il me semble que si, le dynamic_cast est supposé permettre ça, je crois que ça s'appelle le cast croisé...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. retour tableau d'objets par service web axis jboss
    Par TrollMaster dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 27/11/2005, 21h45
  2. Tableau d'objets
    Par moulefrite dans le forum MFC
    Réponses: 7
    Dernier message: 15/06/2004, 14h14
  3. Sauvegarde / Chargement d'un tableau d'objets
    Par Naruto dans le forum Langage
    Réponses: 3
    Dernier message: 18/05/2004, 14h34
  4. [VB6]Tableau d'objet withevents
    Par soazig dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 13/02/2004, 19h44
  5. [VB6] [Syntaxe] Fonction renvoyant un tableau d'objets
    Par Troopers dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 18/10/2002, 15h33

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