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 :

Affectation objet type de base


Sujet :

Langage C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut Affectation objet type de base
    Bonjour a tous,

    L'intitulé n'est pas tres clair mais voici ma question.

    J'ai une classe Objet dont hérite Objet1 Objet2 Objet3 etc..

    J'ai une map d'Objet* qui me permet de stocker mes differents Objet[1-2-3]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::map<std::string, Objet*>
    Quand je veux utiliser cette map je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Object * pObj = getObjInMap( "MaCle" );
    if( dynamic_cast<Objet1*>(pObj) )
    {
    }
    else if( dynamic_cast<Objet2*>(pObj) )
    {
    }
    else if( dynamic_cast<Objet3*>(pObj) )
    {
    }
    Et pour copier ma map je pense faire:
    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
     
    std::map<std::string, Objet*>const_iterator it;
    for(it = mMaMap.begin(); it!=mMaMap.end(); it++)
    {
        if( dynamic_cast<Objet1*>(it->second) )
        {
            Objet1 * pObj = new Objet1(it->second);
        }
        else if( dynamic_cast<Objet2*>(it->second) )
        {
            Objet2 * pObj = new Objet2(it->second);
        }
        else if( dynamic_cast<Objet3*>(it->second) )
        {
            Objet3 * pObj = new Objet3(it->second);
        }
    /*
        Copie de l'objet cree dans la nouvelle map
    */
    }
    Mais je trouve pas ça super dans le sens ou chaque objet qui herite de Objet je devrais rajouter des entrees dans toutes ces methodes.
    Est ce vraiment comme ça qu'il faut faire ou bien y a t il une autre maniere ?

    Merci d'avance

  2. #2
    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
    1. Es-tu obligé de faire un unique map ? Utilises-tu, à un endroit de ton code, le polymorphisme sur ce conteneur ?

    2. Problème annexe : ne peux-tu utiliser autre chose qu'un string comme clé de ton map ?

  3. #3
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    ça dépend du contexte, mais une solution qui fonctionne généralement est le constructeur virtuel (ou clone idiom).
    Je viens juste d'implémenter un conteneur d'objets polymorphes en utilisant ce pattern, et ça marche bien. L'inconvénient principal est qu'il te faut implémenter une fonction clone() pour chaque classe dérivée.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Une map ne contient que des "trucs qui passent pour des objets"

    Vouloir chercher le type exact d'un objet signifie qu'on a perdu trop vite cette information!

    Il y a deux solutions classiques: augmenter l'interface de base (ici, Objet) et diversifier les conteneurs.

    Si tu augmentes objet, tu pourras profiter de l'héritage efficacement.
    Si tu utilises trois maps, plutôt qu'une seule, tu pourras utiliser le type dérivé directement.

    [edit]edit trop rapide, il y a des réponses derrière[/edit]
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Citation Envoyé par oodini Voir le message
    1. Es-tu obligé de faire un unique map ? Utilises-tu, à un endroit de ton code, le polymorphisme sur ce conteneur ?
    Tres bonne remarque, car je viens de voir que non..
    C'est juste que chaque Objet possede cette map qui lui permet de stocker d'autre objets enfants. Cela donne un arbre de donnees a base de Objet[1-X].
    Le probleme c'est que si je veux redefinir l'affectation d'un Objet, je dois recopier tout ses objets enfants de cette map.
    Problème de conception ?
    D'ailleurs je me suis trompe dans mon premeir post mais ca ne change pas le probleme:
    Chaque Objet a une map
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<std::string, ObjectList*>
    Qui contient une liste chainee de ses objets donc en clair:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Objet------> MapObjet1-----------> instance 1 Objet1
    -----------------------------------> instance 2 Objet1
    ------------>MapObjet2------------> instance 1 Objet2
    ------------>MapObjet3------------> instance 1 Objet3
    // Avec Objet de type Objet
    //         MapObjet1 liste chainee de type Objet*
    Citation Envoyé par oodini Voir le message
    2. Problème annexe : ne peux-tu utiliser autre chose qu'un string comme clé de ton map ?
    Donc en fait la string de la map permet de savoir quel sous objet je recherche


    @r0d: Je vais regarder ce principe de constructeur virtuel, je n'ai jamais utilisé et ne connais pas ce principe.

    @leternel: Perdre l'info trop vite, ok, mais comment faire ? Mettre un static membre dans Objet permettant de savoir de quel type est réellement l'objet ? Cela revient en quelque sorte a tenter du dynamic_cast non ? A moins que je vois mal ce que tu voulais dire

  6. #6
    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
    Les informations que tu donnes ne sont permettent pas de conclure.
    Mais je serais toi, je réfléchirai s'il n'y a pas moyen de se passer de polymorphisme.

    Citation Envoyé par sone47 Voir le message
    Donc en fait la string de la map permet de savoir quel sous objet je recherche
    Il faut toujours éviter de mettre un string comme clé. C'est coûteux. Essaye de voir si un enum ne serait pas plus indiqué.
    Cela dit, si tu n'es pas dans un traitement répétitif, ce n'est pas forcément gênant.

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Dans ce cas, tu peux envisager le clonage.

    Tu liras alors avec intérêt ces deux points de la faq:
    la copie polymorphique

    le retour covariant

    ou encore, lire le lien fourni par r0d:
    Citation Envoyé par r0d Voir le message
    Bonjour,

    ça dépend du contexte, mais une solution qui fonctionne généralement est le constructeur virtuel (ou clone idiom).
    Je viens juste d'implémenter un conteneur d'objets polymorphes en utilisant ce pattern, et ça marche bien. L'inconvénient principal est qu'il te faut implémenter une fonction clone() pour chaque classe dérivée.
    À mon avis, ton problème vient de ce que tu implémente un arbre "générique trop tôt"

    Si ton information était correctement structurée (par les bonnes classes), chaque nœud aurait une sémantique choisie, et fournirait les informations utiles et réelles.
    Que veux-tu représenter réellement?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Merci pour vos reponses,

    J'ai regardé les liens pour la copie polymorphe et les retours covariants,
    Il faut que je regarde la compatibilité avec Visual 2010 et GCC 4.1.2.

    @leternel je comprend ta remarque sur le fait de perdre trop tot l'info mais le probleme c'est que je ne vois pas comment faire autrement :/

    @oodini:

    En fait voici l'utilisation que j'ai de ces objets:

    Objet: Classe de base de mes objets
    Objet[1-X]: Objet sur lesquels je travail

    Chaque Objet peut posseder X Objets enfants, classés dans des listes chainées selon leur type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Objet::map<std::string/*pour le type*/, ObjectList /*liste chainee d'objet de type Objet1 ou Objet2...*/>
    Chaque objet peut donc recuperer son n-ieme enfant de type ObjetX ou son objet parent.

    J'utilise 2 methode sur ce conteneur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    addChildren( "Objet1", Objet1*) // Mais du coup quand je fais un add le type est donne car determine par la string..
    getChildren( "Objet1") // Qui me renvoi la liste chainee de mes objets de type Objet1

  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
    Admettons qu'un Objet1 donné ait des enfants de 3 types: Objet3, Objet5, Objet8.

    Dans ce cas, tu peux templatiser tes fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    obj1.addChildren<Objet3>(obj3);
    obj1.getChildren<Objet3>();
    En revanche, cela t'impose d'avoir un conteneur par type d'enfant.
    Et de connaître statiquement ce que tu ajoutes/récupères.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Ok merci je vois le principe.
    Donc vu que mes X types d'objets peuvent avoir comme enfant les X objets, il me faut X conteneurs dans ma classe de base.
    Je ne peux pas templatiser aussi mes conteneurs ?

    Comme ça j'ai mes addCHildren getChildren en template qui mettent a jour une des X map de children en template (je sais pas si je me fais comprendre :/)

    Ou sinon je garde un conteneur mais je fais du dynamic cast dedans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    TYPE getChildren<TYPE> ()
    {
    return dynamic_cast<TYPE>maMap(TYPE);
    }
    Pour ma copie de map je garde le systeme du clonage avec les retours co-variants. Sur Visual 2010, c'est géré. Je vais testé sur GCC mais je pense ils doivent le suppporter.

  11. #11
    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
    Le principe, c'était d'éviter d'utiliser des dynamic_cast.

    D'un autre côté, tu peux contrôler finement quels sont les types d'enfant que tu acceptes.

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    D'accord alors si je pars sur le principe de X conteneurs,
    Il faut que ma fonction template puisse détecter quel conteneur utiliser en fonction du type d'entrée, et.. je ne vois pas comment faire... (conteneur template?)

    Du coup mon objet aurait donc une map de conteneur template qui possedent une liste d'objet en fonction du type.

    Si ce principe est possible, je n'ai plus de souci pour ma copie je templatise mes operateurs copie affectation etc..

    En fait il faut que je fasse un choix entre partir sur ce principe et laisser tel quel et utiliser le clonage.

  13. #13
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Ce que je ne comprend pas, c'est pourquoi tu as besoin de connaitre le type des agrégats (les éléments de ton conteneur polymorphe)? Ca va à l'encontre de l'idée de polymorphisme et du principe EST-UN.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    J'utilise le polymorphisme sur des methodes de base comme init() etc..

    Par contre si dans mon objet1 a un moment donné j'ai besoin de recuperer un de ces enfants de type Objet4 car Objet4 a des membres specifiques avec lesquels je veux bosser il faut bien que je connaisse le type non ?

    Du coup actuellement je fais:

    Objet4 * pObj = dynamic_cast<Objet4*>(getChildren("Objet4"));

    Et si j'ai bien compris je pourrais le passer en template pour m'affranchir de ces strings qui ne sont que les clefs de ma map en interne. Ce qui implique que mes maps en interne doivent etre aussi en template.

    Je pars dans le mur ? :/

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    L'argument, c'est que la plupart du temps le seul qui ait besoin de savoir qu'un objet est de type Objet4, c'est l'Objet4 lui-même: On met alors le code qui s'en occupe dans une fonction virtuelle de Objet, avec les comportements spécifiques dans Objet4.

    Ensuite, si tu veux faire un truc du genre "pour tous les Objet4 du conteneur", tu auras besoin d'un dynamic_cast dans ta boucle. Mais pose-toi quand même la question:
    Ta boucle est-elle vraiment destinée à "tous les Objet4", ou plutôt à tous les descendants de Objet implémentant le comportement X?

    Edit: Aussi, il peut être bon de choisir si le type d'objet est supposé garanti ou non: Si oui, il est préférable de lancer une exception si l'objet n'est pas du type attendu: Soit manuellement, soit en utilisant le dynamic_cast de références, remplaçant pA = dynamic_cast<A*>(pB); par pA = &dynamic_cast<A&>(*pB);
    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.

  16. #16
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Ok en fait ça souleve plusieurs problemes de conception:
    1/ Mon Objet base est beaucoup trop large car les classes qui en dérivent au final n'ont pas du tout les mêmes traitement. Et il y en a beaucoup...

    2/ Mon objet de base possede une map de liste chainee d'objet de base.. Pareil la liste chainee est trop contraignante.. Ou alors il aurait fallu la passer en template

    Je peux donc:
    - Soit revoir la conception du modèle de données mais je pense pas avoir le temps..
    - Soit Templatiser un conteneur qui ferait office de map de liste chainee qui serait plutot un set de liste chainee, dans lequel je définis tout ce qui est affectation copie car c'est de la que vient mon probleme.
    - Soit si je n'ai vraiment pas le temps et que je ne peux pas retoucher laisser tel quel coté utilisation a base de dynamic_cast (je les utilise en fait en reference pour assurer une exception car les objets sont garantis) et utiliser le principe du clonage et retour covariant pour affectation copie.

  17. #17
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Je ne sais pas, c'est difficile à dire car il y a peu d'information.

    Mais d'un point de vue théorique, il y a 2 principes qui pourraient nous aider à démêler la situation.
    1/ LSP: principe de substitution de Liskov. En gros, si tu as une hiérarchie de classes, à n'importe quel endroit de ton programme tu dois pouvoir remplacer n'importe quelle instance d'un type de cette hiérarchie par une instance de n'importe autre type de cette hiérarchie.

    Donc si dans tes classes filles tu as des éléments publics (ou exposés par des accesseurs, ce qui revient au même du point de vue du LSP) qui diffèrent d'un type à l'autre, alors le LSP n'est plus respecté. Et alors tu ne peux plus traiter les objets de ta hiérarchie correctement, tu seras obligé de faire du transtypage, et donc le polymorphisme ne sert plus à rien.

    La solution se trouve peut-être quelque part du côté de la loi de Déméter:
    2/ Déméter: une classe ne doit pas exposer son implémentation (pour faire - très -simple). Si tu as une classe A qui possède un objet de type E, alors 99% des fois il ne faut pas exposer cet objet. Si le programme a besoin de cet objet de type E pour effectuer des traitements, alors ces traitement doivent se faire dans la classe A. Et si ce n'est pas possible ou trop compliqué, alors c'est qu'il y a un problème de conception.

    Objet4 a des membres spécifiques avec lesquels je veux bosser
    C'est là qu'est le problème. Si tu as besoins de traitements spécifiques selon les différents types de ta hiérarchie, alors tous les principes du polymorphisme volent en éclat. La solution est de se débrouiller pour que le protocole (ensemble des fonctions et membres publics de ta classe) soit exactement le même pour les classes filles que pour la classe de base (LSP). Quitte à passer par des intermédiaires (souvent des fonctions libres sont de bonnes solutions).

    Après on ne peut pas entrer plus dans le détails n'en sachant pas plus sur le problème. Peut-être finalement que le problème est que le polymorphisme ne correspond pas à tes besoins.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Ok merci vraiment a tous pour vos reponses.

    le problème est donc la car les 2 principes ne sont pas respectés..
    Les Objets dérivés ont des traitements spécifiques, il y a du cast a tout va donc le polymorphisme est inutilisé.
    Et c'est assez compliqué de redefinir au plus haut niveau les traitements..

    Le point surement bizarre dans ce modele de donnée, c'est que aucun objet n'a d'attributs. Seulement des listes d'enfants, et tout est objet. Donc le champ est beaucoup trop large car Objet peut en fait tout désigner.

    Du coup si je suis dans Objet1 et que je veux réaliser un traitement XXX qui a besoin de objet[4-5-6] je vais faire un getChildren("Objet4") puis pareil avec 5 et 6 et je vais commencer a bosser.

    Le seul point ou le polymorphisme est utilisé est au démarrage ou tout les objets sont construits, et affectés a leur parent. L'objet de plus haut niveau fait un init qui fait un init recursif et donc chacun de ses enfants s'initialise.
    Mais au dela de cet init, il n'a pas ou trop peu de points communs entre tout les objets pour avoir seulement un seul niveau de hiérarchie jusqu'a la base Objet.

    Je pense qu'il manque en fait quelques sous classes sous objets pour préciser un peu le champs d'application d'un type d'objet.

    Ca me blaze un peu tout ça,
    D'un "simple" problème de copie on en arrive a un problème de conception :/
    Et je ne pense pas qu'il sera possible de revenir dessus

  19. #19
    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
    Citation Envoyé par sone47 Voir le message
    D'accord alors si je pars sur le principe de X conteneurs,
    Il faut que ma fonction template puisse détecter quel conteneur utiliser en fonction du type d'entrée, et.. je ne vois pas comment faire... (conteneur template?)
    Il faut spécialiser tes fonctions template.

    Ou alors, mettre toutes tes listes d'objets dans un conteneur boost::any.
    Dans chaque class Object, tu mets un membre int static (un enum serait bienvenu) qui permettra de trouver le bon vecteur dans le vecteur boost::any.

    Ainsi, tu aurais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T>
    std::vector<T>& Object::getObject()
    {
        return mAnyTypedObjectsVectors[T::index];
    }
    Bon, je ne suis pas sûr de la syntaxe, mais tu dois saisir l'idée (tu peux aussi renvoyer un itérateur).

  20. #20
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 366
    Points : 116
    Points
    116
    Par défaut
    Merci,

    J'ai l'impression que je suis partit dans n'importe quoi.

    J'ai définis une classe List template, qui remplacera ma liste chainee
    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
     
    template <typename T> 
    class CList
    { 
    public:
        CList( const std::string & arListName="" );
        CList( const CList<T> & arIn );
        ~CList( );
        long                getSize( void )     { return mSize; };
        long                getCapacity( void ) { return mCapacity; };
        long                addItem( T * pIn );
        long                insItem( T * pIn, long aIdx );
        void                delItem( long aIdx );
        std::string        getName( void );
        void                clear( void );
    protected:
        long                insIn( long aId, T * pIn );
        std::vector<T*>     mPList;
        std::string         mListName;
    };
    Ces listes sont stockées dans un vector de type boost::any, (ou boost variant si je peux specifier les templates autorisés):
    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
     
    class CMapObject
    { 
    public:
        // *** cstror etc..
        template<> 
        T getChildren<T>( int idx){
        // En fonction du type de T (static int type)
        // Je recupere la bonne CList<T> qui est a 
        // l'index type du vecteur boos::any
        // et je renvoie mon objet T present a l'index idx ded ma liste
     
        }
    protected:
        std::vector<boost::any> mVectorList;
    }
    Mais je n'arrive pas a specifier le getChildren..

    Si j'arrive a faire quelque chose comme ça, je n'ai plus(?) de probleme de copie de liste car mon constructeur copie de CList en template s'en charge.
    Et le getChildren en template me permettrai d'avoir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Objet2 = getChildren<Objet2>()
    sans avoir a faire de dynamic cast.
    Par contre je ne comprends pas un truc dans le fait de spécialiser une fonction template, au final je suis obliger de spécifier le type dans l'appel, donc on pourrait dire autant faire une fonction getChildrenObjet1, getChildrenObjet2 etc..

Discussions similaires

  1. Python: différence type de base et objet ?
    Par cal23 dans le forum Général Python
    Réponses: 4
    Dernier message: 18/08/2014, 19h26
  2. Liste des types objet de la base
    Par SheikYerbouti dans le forum Contribuez
    Réponses: 0
    Dernier message: 30/12/2011, 15h25
  3. [héritage] cast avec le type de base
    Par Lere dans le forum C++
    Réponses: 6
    Dernier message: 16/09/2004, 18h21
  4. [FileMaker 6] Questions urgente sur type de base de donnee
    Par LAPLACE dans le forum Autres SGBD
    Réponses: 2
    Dernier message: 06/09/2004, 17h39
  5. [CR]Changement de type de base de donnée
    Par nabil dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 12/04/2004, 22h42

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