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 :

Utilisation des templates ou allocation dynamique


Sujet :

C++

  1. #1
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut Utilisation des templates ou allocation dynamique
    Bonjour les gens !

    Une fois de plus je reviens pour mon projet de gestion d'horaire..

    Suite aux conseils, j'ai maintenant bien séparé tout mes objets : job, date, time et employer sont stockés dans des maps(ObjectContainer), réunis par leur iD pour chaque mission qui les utilises : mission[ 1 ]( int idJob, idDate, idTime, idEmployer )
    Ils se composent tous de fonctions communes. ( Print(), operator <, operator ==)
    J'ai une classe data qui réunie les objets instanciés.

    J'ai tout d'abord rendu les membres de data publiques. Je devais donc faire un switch à chaque endroits où je les utilisaient.
    J'ai alors essayé d'en faire appel directement dans data par un switch template et un enum, cependant, même si elle répondent de la même manière, je suis obligé de préciser le type dans chacune des parties ou je les utilises. ( <Name> ou <Date> ou ...)
    En gros, je suis obligé de répéter ce switch à chaque fois.

    Data.h
    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
    35
    36
    37
    38
    39
    40
    #include <string>
    #include <vector>
    #include <map>
     
    #include "Object.h"
     
    class Data {
    public:
            Data() {}
     
            template < class T >//Mon getter qui me renvoie l'objet voulu.
            const T& Get( const char TYPE ) const {//Possibilité de l’appeler grâce à son nom
                    switch( TYPE ) {//Le type
                    case JOB:
                            return job;//Je dois préciser le type < Name > pour l'utiliser
                            break;
                    case DATE:
                            return date;//Je dois préciser le type < Date >
                            break;
                    case TIME:
                            return time;//...
                            break;
                    case EMPLOYER:
                            return employer;
                            break;
                    }
            }
            std::vector< Mission > mission;//Vecteur de mission( const int job, date, time, employer )
     
    private:
            Data( const Data& ) = delete;
            Data& operator= ( const Data& ) = delete;
     
            ObjectContainer< Name > job;//Cette classe template contient une map de noms correspondant aux jobs
            ObjectContainer< Date > date;
            ObjectContainer< Time > time;
            ObjectContainer< Name > employer;
    };
     
    #endif // DATA_H_INCLUDED
    Object.h
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    #ifndef OBJECT_H_INCLUDED
    #define OBJECT_H_INCLUDED
     
    #include <iostream>
    #include <string>
     
    //==========================================================
    //ENUM TYPE
    //==========================================================
    enum {
            NOTHING,
            JOB,
            DATE,
            TIME,
            EMPLOYER,
            MISSION
    };
    //==========================================================
    //ID GENERATOR Renvoi un Id toujours positif
    //==========================================================
    //...
    //==========================================================
    //CLASS Name
    //==========================================================
    //...
    //==========================================================
    //CLASS Date
    //==========================================================
    //...
    //==========================================================
    //CLASS Time
    //==========================================================
    //...
    //==========================================================
    //CLASS ObjectContainer
    //==========================================================
    template < class T >
    class ObjectContainer {
    public:
            ObjectContainer() {}
     
            void Print( const int objectId ) { table[ objectId ].Print(); }//Les objets référencés doivent contenir cette fonction
     
            const int Create( const T& t ) {
                    int searchId( -1 );
                    typedef typename std::map< const int, T >::iterator TableIt;
                    for( TableIt tableIt( table.begin()); tableIt != table.end(); tableIt++ ) {
                            if( tableIt->second == t ) {
                                    searchId = tableIt->first;
                            }
                    }
                    if( searchId == -1 ) {
                            const int id( idGen.Create());
                            table[ id ] = t;
                            searchId = id;
                    }
                    return searchId;
            }
            const T& Get( const int iD ) { return table[ iD ]; }
     
    private:
            std::map< const int, T > table;
            IdGenerator idGen;//
    };
    //==========================================================
    //CLASS Mission
    //==========================================================
    class Mission {
    public:
            Mission( const char job, const char date, const char time, const char employer = NOTHING ) : job( job ),
                                                                                            date( date ),
                                                                                            time( time ),
                                                                                            employer( employer ) {
            }
            const char Get( const int TYPE ) const {
                    switch( TYPE ) {
                    case NOTHING:
                            return NOTHING;
                            break;
                    case JOB:
                            return job;
                            break;
                    case DATE:
                            return date;
                            break;
                    case TIME:
                            return time;
                            break;
                    case EMPLOYER:
                            return employer;
                            break;
                    }
            }
    private:
            char job;
            char date;
            char time;
            char employer;
    };
     
    #endif // OBJECT_H_INCLUDED
    Ce que j'aimerais obtenir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void DataReader::Print( const int TYPE_1, const int TYPE_2, const int TYPE_3, const int TYPE_4, const Mission& mission ) const {//Afficher les éléments de la missions dans un ordre choisi en amont
                                    data.Get( TYPE_1 ).Print( mission.Get( TYPE_1 ));
            if( TYPE_2 != NOTHING ) data.Get( TYPE_2 ).Print( mission.Get( TYPE_2 ));
            if( TYPE_3 != NOTHING ) data.Get( TYPE_3 ).Print( mission.Get( TYPE_3 ));
            if( TYPE_4 != NOTHING ) data.Get( TYPE_4 ).Print( mission.Get( TYPE_4 ));
    }
    N'y a t-il aucun autre moyen de faire, que passer par l'allocation dynamique et l’héritage pour solutionner ce problème ?

    PS(On m'a dit que l'héritage était mauvais pour définir des comportements, dans le cadre d'une factory, ce ne sont pas les comportements mais bien les objets qui y sont définis ?!? Son utilisation est donc tout à fait appropriée ?!)

    Une fois de plus merci !

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


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

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 575
    Points
    218 575
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Wow, je suis étonné de répondre en premier après une journée, sur ce forum. Enfin bref, passons.

    Il y a une chose qu'il ne faut pas oublier avec les templates, c'est que les templates sont des choses qui sont déterminer à la compilation. Dans le sens, c'est lors de la création du programme/compilation que l'on sait quel est le type, quelle est la donnée à utiliser. L'héritage/allocation dynamique permet de déterminer le type de la donnée à la volée pendant une exécution.

    Toutefois, on peut toujours arriver à tricher, en créant une classe mère, pour généraliser des templates, mais dans ce cas là, on perdra quelques avantages (une fois que l'on est passé sous la forme généraliste, il est dur de refaire marche arrière, ou d'appeler des fonctions spécifiques à une classe fille spécifique (bon ça peut aussi être un problème de conception )).

    Là, pour votre Get(), vous êtes sur que vous pouvez l'appeler sans avoir besoin de faire Get<Type>(enumType) ?
    Dans ce cas, pas besoin de template, d'ailleurs, car la valeur passé donne l'information (principe d'une Factory), je pense.

    Faudra peut être regarder le pattern politique, mais je suis pas très sur de moi (je vais me faire démonte par ram/gbdivers et autre) -> http://en.wikipedia.org/wiki/Policy-based_design
    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
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Wow, je suis étonné de répondre en premier après une journée, sur ce forum. Enfin bref, passons.
    Je ne m'exprime pas vraiment clairement, ça en a sans doute rebuté plus d'un
    Toutefois, on peut toujours arriver à tricher, en créant une classe mère, pour généraliser des templates, mais dans ce cas là, on perdra quelques avantages (une fois que l'on est passé sous la forme généraliste, il est dur de refaire marche arrière, ou d'appeler des fonctions spécifiques à une classe fille spécifique (bon ça peut aussi être un problème de conception )).
    J'ai essayé avec une classe mère, seulement ça fait pas mal de pointeurs !
    (J'ai peut être aussi trop tendance à vouloir tout passer par référence..)
    De plus celle-ci se voit attribuer beaucoup de fonctions virtuelles.
    Et d'autre s'en rajouterons si on incorpore un nouveau type d'objet.
    Il y a une chose qu'il ne faut pas oublier avec les templates, c'est que les templates sont des choses qui sont déterminer à la compilation. Dans le sens, c'est lors de la création du programme/compilation que l'on sait quel est le type, quelle est la donnée à utiliser.
    J'ai donc restreins l'utilisation des templates à la classe où sont définis les différents objets.
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    #ifndef DATA_H_INCLUDED
    #define DATA_H_INCLUDED
     
    #include <string>
    #include <vector>
     
    #include "Object.h"
     
    class Data {
    public:
            Data() {
                    jobTable.Create( Name(""));//Valeur par défaut si une des information n'est pas donnée
                    dateTable.Create( Date( 0, 0, 0 ));
                    timeTable.Create( Time( 0 ));
                    employerTable.Create( Name(""));
            }
     
            void Print( const char TYPE, const int iD ) {
                    switch( TYPE ) {
                    case JOB:
                            jobTable.Print( iD );
                            break;
                    case DATE:
                            dateTable.Print( iD );
                            break;
                    case TIME:
                            timeTable.Print( iD );
                            break;
                    case EMPLOYER:
                            employerTable.Print( iD );
                            break;
                    }
            }
     
            const bool SmallerThan( const char TYPE, const int iD_1, const int iD_2 ) {
                    switch( TYPE ) {
                    case JOB:
                            return jobTable.SmallerThan( iD_1, iD_2 );
                            break;
                    case DATE:
                            return dateTable.SmallerThan( iD_1, iD_2 );
                            break;
                    case TIME:
                            return timeTable.SmallerThan( iD_1, iD_2 );
                            break;
                    case EMPLOYER:
                            return employerTable.SmallerThan( iD_1, iD_2 );
                            break;
                    }
                    return false;
            }
     
            const int CreateJob( const Name& name ) { return jobTable.Create( name ); }
            const int CreateDate( const Date& date ) { return dateTable.Create( date ); }
            const int CreateTime( const Time& time ) { return timeTable.Create( time ); }
            const int CreateEmployer( const Name& name ) { return employerTable.Create( name ); }
     
            void CreateMission( const Name& job, const Date& date, const Time& time, const Name& employer ) {
                    mission.push_back( Mission( CreateJob( job ), CreateDate( date ), CreateTime( time ), CreateEmployer( employer )));
            }
            void CreateMission( const Name& job, const Date& date, const Time& time ) {
                    mission.push_back( Mission( CreateJob( job ), CreateDate( date ), CreateTime( time )));
            }
     
            std::vector< Mission > mission;
     
    private:
            Data( const Data& ) = delete;
            Data& operator= ( const Data& ) = delete;
     
            ObjectContainer< Name > jobTable;
            ObjectContainer< Date > dateTable;
            ObjectContainer< Time > timeTable;
            ObjectContainer< Name > employerTable;
    };
    #endif // DATA_H_INCLUDED
    Si on rajoute un objet, les changements se feront tous dans cette classe.
    Je peux maintenant m'en servir ainsi :
    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
    int main() {
            Data data;
     
            data.CreateMission( Name("JOB_1"), Date( 7, 12, 2005 ), Time( 5, 35 ), Name( "Adecco" ));
            data.CreateMission( Name("JOB_1"), Date( 8, 12, 2005 ), Time( 6, 10 ), Name( "Adecco" ));
            data.CreateMission( Name("JOB_2"), Date( 9, 12, 2005 ), Time( 6, 10 ));
            data.CreateMission( Name("JOB_2"), Date( 10, 12, 2005 ), Time( 6, 10 ));
            data.CreateMission( Name("JOB_1"), Date( 11, 12, 2005 ), Time( 6, 10 ), Name( "Adecco" ));
     
            int TYPE = JOB;
            data.Print( TYPE, data.mission[ 1 ].Get( TYPE ) );//Imprimer l'élement mission 1 selon le type
            TYPE = DATE;
            data.Print( TYPE, data.mission[ 1 ].Get( TYPE ) );
     
            if( data.SmallerThan( TYPE, data.mission[ 1 ].Get( TYPE ), data.mission[ 2 ].Get( TYPE ) ))//Trier les élements de mission 1 et mission 2 selon le type
                    data.Print( TYPE, data.mission[ 1 ].Get( TYPE ) );
     
            return 0;
    }
    Ce n'est sans doute pas la meilleure méthode, promis je me lance dans les factory
    Faudra peut être regarder le pattern politique
    Ca m'a l'air d'être plus lisible que ce que j'ai fait, et le principe à l'air d'être plus ou moins équivalent !

    Je vous remercie !

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


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

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 575
    Points
    218 575
    Billets dans le blog
    120
    Par défaut
    Je pense que pour des objets Date/Job/... qui n'ont rien en comment, il n'y a aucune raison (dans ma tête) d'essayer de faire en sorte qu'ils soient tous pareille.
    La classe Data est elle un conteneur ?
    Data pourrait être template, pour conteneur soit des Date, des Job ou autres. Et si vous avez besoin, vous pouvez faire encore une classe au dessus, qui contient des Data<Job> / Data<Date> / ... qui exposerait des fonctions pour récupérer les différents données. (Ou même une fonction Get spécialisée selon le type de la données voulue).

    Mais peut être que je m'y perd. Quels sont vos vraies besoins ?
    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.

  5. #5
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Quels sont vos vraies besoins ?
    Désolé, j'ai oublié de marquer comme résolut. J'ai trouvé une solution, c'était un souci de répétition des templates, ce que j'ai tenté d'expliquer post précédent.

    Ces objets sont similaires par leurs utilisation ( comparer, imprimer .. )
    Mes leurs fonctions sont différentes ( comparer deux noms : string==string, comparer deux date : comparer l'année puis le mois puis le jour )

    Data pourrait être template, pour conteneur soit des Date, des Job ou autres. Et si vous avez besoin, vous pouvez faire encore une classe au dessus, qui contient des Data<Job> / Data<Date> / ... qui exposerait des fonctions pour récupérer les différents données.
    C'est du coup ainsi que j'ai procédé,

    data est ma classe template : ObjectContainer.
    classe du dessus est ma classe : Data

    Je ne fait plus de Getter en dehors de data, seulement des fonctions peuvent atteindre mes objets( Compare( TYPE, id1, id2) Print( TYPE, iD )). Je ne suis pas obligé de préciser un type de template pour les utiliser.

    Mon problème reste de l'ordre de l'organisation, mais j'y bosse dur ! Merci

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

Discussions similaires

  1. Utilisation des templates
    Par vanitom dans le forum MFC
    Réponses: 21
    Dernier message: 01/08/2007, 11h07
  2. Réponses: 7
    Dernier message: 13/02/2007, 15h09
  3. Réponses: 1
    Dernier message: 24/11/2006, 16h36
  4. [XSL] utilisation des templates
    Par KibitO dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 16/12/2005, 15h54
  5. Utilisation des templates
    Par mikky dans le forum C++
    Réponses: 1
    Dernier message: 14/09/2005, 12h59

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