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 :

question de design


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut question de design
    Bonjour :-)

    Je viens avec une question de design. Le but du code que nous développons (open source, c'est beau, hein ?) est de modéliser des systèmes physiques particuliers. On va devoir reproduire le comportement de quatre entités de base - des lignes - et elles devront être gérés par des classes adaptées. Mais certaines d'entre elles auront des morceaux d'algorithmes identiques, d'autres non.
    il y aura des fonctions type operator ==, mais renvoyant parfois des tribool, et qui dépendront du type de ligne à traiter. Tous ces objets lignes sont contenus dans des graph, conteneurs doués de certaines fonctions ad-hoc, et différentes classes peuvent travailler sur ces graphes.

    Pour le moment, je fais un petit démonstrateur de la solution envisagée, à base d'object factory et d'abstract factory, mais c'est surtout l'organisation en classe qui me fait souci. Ci-dessous un petit bout de code.
    Pour résumer : les lignes dérivent d'une classe BaseLine, et ajoutent des données membres suivant leur type physique, sur lesquelles pourront porter des opérations spécifiques.
    les graph suivent des types analogues, mais possèdent tous un même conteneur vers une liste de BaseLine* (a priori pas trop le choix, parce que les lignes seront créées par l'abstract factory et sauf erreur de ma part, il faut bien que les objets line qui en sortent dérivent du même type de base, non ?)
    Ce qui me chiffonne c'est que je me trouve contraint de faire du static_cast dans le graph dérivé du graph de base pour faire appelle aux propriétés spécifiques des lignes dérivées... est-ce logique ?
    Y a-t-il une astuce pour les fonctions coincide, autre que de les mettre dans des namespace pour pouvoir appeler la bonne au sein des différentes classes ?
    Pour les différentes classes qui vont travailler sur graph suivant son type - et donc le type des lignes - on risque d'avoir des problèmes analogues... ce qui me fait me demander si notre approche est saine ?

    Voili voilou, si vous avez des suggestions, je suis carrément preneur !

    Merci beaucoup :-)

    Hugo/Marc








    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
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    #include <iostream>
    #include<list>
    #include<boost/foreach.hpp>
     
    using namespace std;
     
    //=============================================
    //Les classes lines
    //=>une base et deux dérivées
    //=============================================
     
    //classe de base
    class BaseLine{
        public:
        virtual void Action();
        unsigned GetTag(){return _tag;}
     
        BaseLine(unsigned t):_tag(t){}
        virtual ~BaseLine(){}
     
        protected:
        unsigned _tag;
    };
    void BaseLine::Action(){cout << "Action de BaseLine avec tag : " << _tag << endl; }
     
    //première classe dérivée
    class PlaneLine : public BaseLine{
     
        public:
        PlaneLine(unsigned t, int p):BaseLine(t),_plane(p){}
        int GetPlane(){return _plane;}
        void Action();
     
        private:
        int _plane;
     
    };
    void PlaneLine::Action(){cout << "Action de PlaneLine avec tag : " << _tag << " et plane : "<<_plane << endl;}
     
    //deuxième classe dérivée
    class FaultedLine : public BaseLine{
        public:
        FaultedLine(unsigned t, int p, int f):BaseLine(t),_plane(p),_fault(f){}
        ~FaultedLine(){}
        void Action();
     
        private:
        int _plane;
        int _fault;
    };
    void FaultedLine::Action(){cout << "Action de FaultedLine avec tag : " << _tag << ", plane : "<<_plane <<" et faute : "<< _fault << endl;}
     
    //==============================================
    //Les classes graph : une base et deux dérivées
    //==============================================
     
    //===================
    //la classe de base 
    //===================
     
    class GraphBase{
     
    public:
    //interface et constructeur
    virtual void Action();
     
    virtual ~GraphBase()
    {
        BOOST_FOREACH(BaseLine* l,_lines)
           delete l;
    }
    GraphBase(unsigned t):_tag(t){}
    void PushLine(BaseLine* l){_lines.push_back(l);}
     
    protected:
     
    //quelques algo communs à tout le monde
     
    void MethodeElem1();
    void MethodeElem2(BaseLine* line);
     
    unsigned _tag;
    list<BaseLine*> _lines;
    };
     
    void GraphBase::MethodeElem1()
    {
        cout << "Méthode élém 1 de GraphBase" << endl;
        BOOST_FOREACH(BaseLine* l,_lines)
           l->Action();
    }
     
    void GraphBase::MethodeElem2(BaseLine* line)
    {
        cout <<" MéthodeElem2 de la classe GraphBase" << endl;
        cout << " sur la ligne : " << line->GetTag() << endl;
    }
     
    void GraphBase::Action()
    {
        cout << "Action de GraphBase - tag : "<<_tag << endl;
        MethodeElem1();
        BOOST_FOREACH(BaseLine* l,_lines)
          MethodeElem2(l);
    }
     
     
    //=====================
    //la classe GraphPlane
    //=====================
    class GraphPlane: public GraphBase
    {
        public :
        GraphPlane(unsigned t):GraphBase(t){}
        void Action();
     
        private:
        void AlgoSpecPlane();
    };
     
    void GraphPlane::AlgoSpecPlane()
    {
        cout << "GraphPlane::AlgoSpecPlane du graph # " << _tag << endl;
        BOOST_FOREACH(BaseLine* pl,_lines)
          cout << "line #" << static_cast<PlaneLine*>(pl)->GetTag() << " Plane # " << static_cast<PlaneLine*>(pl)->GetPlane() << endl;
    }
     
    void GraphPlane::Action()
    {
        cout << "Action de GraphPlane Graph # " << _tag << endl;
        AlgoSpecPlane();
        MethodeElem1();
    }
     
     
     
    int main()
    {
        //on crée deux graph
        GraphBase* gb = new GraphBase(0);
        GraphBase* gp = new GraphPlane(1);
     
        //on crée des lignes de base
        BaseLine* bl0 = new BaseLine(0);
        BaseLine* bl1 = new BaseLine(1);
        BaseLine* bl2 = new BaseLine(2);
        BaseLine* bl3 = new BaseLine(3);
        //on crée des lignes avec plan
        BaseLine* pl0 = new PlaneLine(0,-1);
        BaseLine* pl1 = new PlaneLine(1,1);
        BaseLine* pl2 = new PlaneLine(2,1);
        BaseLine* pl3 = new PlaneLine(3,-1);
     
        //on stocke tout ce petit monde où c'est logique
        gb->PushLine(bl0);gb->PushLine(bl1);gb->PushLine(bl2);gb->PushLine(bl3);
        gp->PushLine(pl0);gp->PushLine(pl1);gp->PushLine(pl2);gp->PushLine(pl3);
     
        gb->Action();
        gp->Action();
     
        return 1;
    }

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Tu as oublié d'interdire la copie et l'opérateur d'affectation pour tes classes polymorphique à première vue. Et de même l'opérateur == sur une classe à sémantique d'entité ce n'est pas l'idéal je pense.

    Sinon, je ne comprend pas pourquoi tu as besoin d'hériter en graph du premier ? A première vue tes graphes ne font que gérer un conteneur avec quelque méthodes particulières (d'ailleur des algo sous forme de fonction libre travaillant avec des itérateurs au besoin ne serait pas mieux ?).

    Pour le moment je ne peus pas en dire plus sans comprendre pourquoi il y a cet héritage.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut
    Bonjour Flob 90,

    Merci pour ta réponse. Je vais faire évoluer un peu l'exemple - hyper fruste pour le moment - j'espère que nos "soucis" apparaîtront mieux...

    Hugo

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut
    Voici donc qqch de plus abouti :
    en fait, toutes les classes sont contenues dans une classe Num, qui est une interface pour différents codes appelant.
    Des objets de type graph variés vont être contenus dedans et des objets de calcul de force ou autre de type adapté devront agir dessus (toute la partie création est ad-hoc). Ce qui me titille, c'est le besoin de faire du static_cast ? Pourrait-on faire mieux à l'aide de templates ? Est-ce que ce design présente des défauts évidents - et que je ne vois pas ;-) ?

    Merci tout plein !!

    Hugo/Marc




    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
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    #include <iostream>
    #include<list>
    #include<boost/foreach.hpp>
     
    using namespace std;
     
    //=============================================
    //Les classes lines
    //=>une base et deux dérivées
    //=============================================
     
    //classe de base
    class BaseLine{
        public:
        virtual void Action();
        unsigned GetTag(){return _tag;}
     
        BaseLine(unsigned t):_tag(t){}
        virtual ~BaseLine(){}
     
     
        friend bool Coincide(BaseLine* b1, BaseLine* b2);
     
        protected:
        unsigned _tag;
    };
    void BaseLine::Action(){cout << "Action de BaseLine avec tag : " << _tag << endl; }
     
    //premiere classe dérivée
    class PlaneLine : public BaseLine{
     
        public:
        PlaneLine(unsigned t, int p):BaseLine(t),_plane(p){}
        int GetPlane(){return _plane;}
        void Action();
     
        friend bool Coincide(PlaneLine* b1, PlaneLine* b2);
        private:
        int _plane;
     
    };
    void PlaneLine::Action(){cout << "Action de PlaneLine avec tag : " << _tag << " et plane : "<<_plane << endl;}
     
    //deuxieme classe dérivée
    class FaultedLine : public BaseLine{
        public:
        FaultedLine(unsigned t, int p, int f):BaseLine(t),_plane(p),_fault(f){}
        ~FaultedLine(){}
        void Action();
        int GetPlane(){return _plane;}
        int GetFault(){return _fault;}
     
        private:
        int _plane;
        int _fault;
    };
    void FaultedLine::Action(){cout << "Action de FaultedLine avec tag : " << _tag << ", plane : "<<_plane <<" et faute : "<< _fault << endl;}
     
    bool Coincide(BaseLine* b1, BaseLine* b2)
    {
        cout << "Coincide BaseLine"<< endl;
        if (b1->_tag == b2->_tag) return true;
    	return false;
    }
     
     
     
    bool Coincide(PlaneLine* b1, PlaneLine* b2)
    {
        cout << "Coincide PlaneLine"<< endl;
        if (b1->_tag == b2->_tag && b1->_plane == b2->_plane) return true;
    	return false;
    }
     
    //un typedef pratique
    typedef list<BaseLine*>::iterator it_l_bl;
     
    //==============================================
    //Les classes graph : une base et deux dérivées
    //==============================================
     
    //===================
    //la classe de base 
    //===================
     
    class GraphBase{
     
    public:
    //interface et constructeur
    virtual void Action();
    it_l_bl GetFirstLine(){return _lines.begin();}
    it_l_bl GetLastLine(){return _lines.end();}
     
    virtual ~GraphBase()
    {
        BOOST_FOREACH(BaseLine* l,_lines)
           delete l;
    }
    GraphBase(unsigned t):_tag(t){}
    void PushLine(BaseLine* l){_lines.push_back(l);}
     
    protected:
     
    //quelques algo communs a tout le monde
     
    void MethodeElem1();
    void MethodeElem2(BaseLine* line);
     
    unsigned _tag;
    list<BaseLine*> _lines;
    };
     
    void GraphBase::MethodeElem1()
    {
        cout << "Méthode élém 1 de GraphBase" << endl;
        BOOST_FOREACH(BaseLine* l,_lines)
           l->Action();
    }
     
    void GraphBase::MethodeElem2(BaseLine* line)
    {
        cout <<" MéthodeElem2 de la classe GraphBase" << endl;
        cout << " sur la ligne : " << line->GetTag() << endl;
    }
     
    void GraphBase::Action()
    {
        cout << "Action de GraphBase - tag : "<<_tag << endl;
        MethodeElem1();
        BOOST_FOREACH(BaseLine* l,_lines)
          MethodeElem2(l);
    }
     
     
    //=====================
    //la classe GraphPlane
    //=====================
    class GraphPlane: public GraphBase
    {
        public :
        GraphPlane(unsigned t):GraphBase(t){}
        void Action();
     
        private:
        void AlgoSpecPlane();
    };
     
    void GraphPlane::AlgoSpecPlane()
    {
        cout << "GraphPlane::AlgoSpecPlane du graph # " << _tag << endl;
        BOOST_FOREACH(BaseLine* pl,_lines)
          cout << "line #" << static_cast<PlaneLine*>(pl)->GetTag() << " Plane # " << static_cast<PlaneLine*>(pl)->GetPlane() << endl;
    }
     
    void GraphPlane::Action()
    {
        cout << "Action de GraphPlane Graph # " << _tag << endl;
        AlgoSpecPlane();
        MethodeElem1();
    }
     
     
     
    //===============================
    //les classes de calcul de force
    //===============================
     
     
    //===============================
    //la classe de base
    //===============================
    class ForceBase{
        public:
        virtual void Calcul(GraphBase* g);
        ForceBase(int f):_force(f){}
        virtual ~ForceBase(){}
     
        protected:
        void ForceElementaire(GraphBase* g);
        int _force;
    };
     
    void ForceBase::Calcul(GraphBase* g)
    {
        ForceElementaire(g);
    }
     
    void ForceBase::ForceElementaire(GraphBase* g)
    {
      cout << "ForceBase::ForceElementaire ";
    for(it_l_bl line = g->GetFirstLine() ; line != g->GetLastLine() ; line++){
      _force = _force + (*line)->GetTag();
      cout << _force << " " ;
     }
     cout << endl;
    }
     
     
    //===============================
    //la classe pour graph plans
    //===============================
    class ForcePlane:public ForceBase{
        public:
        void Calcul(GraphBase* g);
        ForcePlane(int f):ForceBase(f){}
     
        private:
        void ForceOfPlan(GraphBase* g);
    };
     
    void ForcePlane::Calcul(GraphBase* g)
    {
        cout << "ForcePlane::Calcul ";
        ForceElementaire(g);
        ForceOfPlan(g);
        cout << endl;
    }
     
    void ForcePlane::ForceOfPlan(GraphBase* g)
    {
        cout << "ForcePlane::ForceOfPlan ; ";
        for(it_l_bl line = g->GetFirstLine() ; line != g->GetLastLine() ; line++){
            _force = _force + static_cast<PlaneLine*>(*line)->GetPlane();
    	cout << _force << " ";
        }
        cout << endl;
    }
     
     
    //===============================
    //les classes de minimisation
    //===============================
     
     
    //===============================
    //la classe de base
    //===============================
    class MinimiseBase{
        public:
        MinimiseBase(int m):_minimum(m){}
        virtual void Min(GraphBase* g);
        virtual ~MinimiseBase(){}
     
        protected:
        int _minimum;
    };
     
    void MinimiseBase::Min(GraphBase* g)
    {
        cout << "MinimiseBase::Min" <<endl;
        for(it_l_bl line1 = g->GetFirstLine() ; line1 != g->GetLastLine() ; line1++){
            for(it_l_bl line2 = g->GetFirstLine() ; line2 != g->GetLastLine() ; line2++){
    	    if(*line1 != *line2){
    		if(Coincide(*line1,*line2)){
    	            _minimum +=(*line1)->GetTag()-(*line2)->GetTag();	
    		}
    	    }
    	}
        }
        cout << "fin MinimiseBase::Min" << endl;
    }
     
     
    //===============================
    //la classe pour plan
    //===============================
    class MinimisePlane:public MinimiseBase{
        public:
        MinimisePlane(int m ):MinimiseBase(m){}
        void Min(GraphBase* g);
        ~MinimisePlane(){}
     
    };
     
    void MinimisePlane::Min(GraphBase* g)
    {
        cout << "MinimisePlane::Min" <<endl;
        for(it_l_bl line1 = g->GetFirstLine() ; line1 != g->GetLastLine() ; line1++){
            for(it_l_bl line2 = g->GetFirstLine() ; line2 != g->GetLastLine() ; line2++){
                if(*line1 != *line2){
                    if(Coincide(static_cast<PlaneLine*>(*line1),static_cast<PlaneLine*>(*line2))){
                        _minimum +=(*line1)->GetTag()-(*line2)->GetTag();
                    }
                }
            }
        }
        cout << "fin MinimisePlane::Min" <<endl;
    }
     
     
    //=====================
    //la classe num
    //=====================
     
    struct Element{
       GraphBase* graph;
       ForceBase* force;
       MinimiseBase* minimise;
       Element(GraphBase* g,ForceBase* f,MinimiseBase* m):graph(g),force(f),minimise(m){}
    };
     
    class Num{
        public:
        void Force();
        void Minimise();
        void Action();
        void Push(Element* el){_elements.push_back(el);}
        ~Num();
        private:
        list<Element*>_elements;
    };
     
    Num::~Num()
    {
        BOOST_FOREACH(Element* el,_elements)
         {
    	 delete el->graph;
    	 delete el->force;
    	 delete el->minimise;
         }
    }
     
    void Num::Action()
    {
        cout << "======ACTION====="<< endl;
        BOOST_FOREACH(Element* el,_elements)
         {
    	 cout <<"Action"<<endl;
            el->graph->Action();
         }
         cout << endl << endl << endl;
    }
     
    void Num::Force()
    {
        cout << "======FORCE====="<< endl;
        BOOST_FOREACH(Element* el,_elements)
         {
    	 cout <<"Force"<<endl;
            el->force->Calcul(el->graph);
         }
         cout << endl << endl << endl;
    }
     
    void Num::Minimise()
    {
        cout << "======MINIMISE====="<< endl;
        BOOST_FOREACH(Element* el,_elements)
         {
    	 cout <<"Minimise"<<endl;
            el->minimise->Min(el->graph);
         }
         cout << endl << endl << endl;
    }
     
     
     
    //=======================
    //Le main
    //=======================
    int main()
    {
        //on crée deux graph
        GraphBase* gb = new GraphBase(0);
        GraphBase* gp = new GraphPlane(1);
     
        //on crée des lignes de base
        BaseLine* bl0 = new BaseLine(0);
        BaseLine* bl1 = new BaseLine(1);
        BaseLine* bl2 = new BaseLine(2);
        BaseLine* bl3 = new BaseLine(3);
        //on crée des lignes avec plan
        BaseLine* pl0 = new PlaneLine(0,-1);
        BaseLine* pl1 = new PlaneLine(1,1);
        BaseLine* pl2 = new PlaneLine(2,1);
        BaseLine* pl3 = new PlaneLine(3,-1);
     
        //on stocke tout ce petit monde où c'est logique
        gb->PushLine(bl0);gb->PushLine(bl1);gb->PushLine(bl2);gb->PushLine(bl3);
        gp->PushLine(pl0);gp->PushLine(pl1);gp->PushLine(pl2);gp->PushLine(pl3);
     
        //On cree l'objet num
        Num* num = new Num();
     
        //on cree les structures pour les pusher
        ForceBase* fb = new ForceBase(0);
        MinimiseBase* mb = new MinimiseBase(0);
        Element* elt = new Element(gb,fb,mb);
        num->Push(elt);
     
        ForceBase* fp = new ForcePlane(0);
        MinimiseBase* mp = new MinimisePlane(0);
        elt = new Element(gp,fp,mp);
        num->Push(elt);
     
        num->Action();
        num->Minimise();
        num->Force();
     
        delete num;
     
        return 1;
    }

  5. #5
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    (oublie pas d'interdire la copie et l'affectation à chaque fois)

    Donc si je comprend bien tes graphes sont utilisé comme des conteneurs, à ce titre l'héritage de conteneur n'est probablement pas une bonne idée.

    Si je comprend bien, Force sert pour le calcul des forces, si c'est le cas il ne devrait pas, AMA, faire de distinction entre les différentes type de Line, en jouant avec le polymorphisme tu devrais pouvoir faire que Force ne fait que passer des données à chaque Line et que chaque Line retourne les données nécessaire au calcul. En gros déléguer le travaille de distinction de type (via tes static_cast) aux classes Lines elle-même (via le polymorphisme).

    (C'est une idée rapide, je regarderais plus en détail plus tard, il y a peut-etre des éléments que je n'ai pas encore vue)

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut
    Merci beaucoup pour tes réponses et tes suggestions !! Je vais y réfléchir.

    En fait, graph est propriétaire des lignes, mais est aussi responsable de certaines opérations qui dépendent du type des lignes qu'il contient. On a peut être mal réparti les responsabilités dans cette affaire... ? il peut recoller des lignes, notamment, et cette fonction est fortement dépendante de leur type, par exemple.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut
    Pour mettre un peu en mot :
    Un des aspects du problèmes, pour ce que j'en comprends, c'est de créer des objets comme force, qui correspondent au type des lignes qu'ils vont traiter, ce type étant unique sur tout le graph (conteneur amélioré, disons). Pour le moment, ma philosophie était de passer par une abstract factory pour la création, de stocker les graph et compagnie de manière associative dans la grande classe num. Comme ça, les objets savent qu'ils travaillent sur tel ou tel type et peuvent utiliser du static_cast de manière safe... mais c'est peu satisfaisant, et ça donne l'impression d'un problème de conception fondamental. Avec ça, il y a les fonctions coincide - très importantes pour nous - qui doivent s'adapter également au type des lignes...

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut
    Bon, je commence à être capable de résumer mon problème - à défaut de savoir le résoudre ;-).

    En gros, on va devoir gérer des populations de conteneurs hétérogènes. Ces "conteneurs" (graph) contiendront un seul type de ligne, mais au sein d'une simulation, il y aura une famille de graph contenant des lignes de type différents : ces graph seront donc associés avec les objets capables d'agir sur les lignes suivant leur type. Seulement dans graph, je dispose de pointeurs vers le type de base alors que les classes filles peuvent être dotées de propriétés très différentes de la classe mère : cela veut-il dire que je dois définir une interface dans la classe de base qui soit suffisamment large pour intégrer tous les cas de figure des classes dérivées pour satisfaire la demande des différentes autres fonctions ? Vaut-il mieux utiliser du transtypage ? y a-t-il d'autres astuces ? Bref, je m'y perds un peu...

    Merci :-)

    Marc

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    En fait, ce que tu appelle graphes pourrait être... une collection de ligne agissant comme un visiteur.

    tu aurais alors, effectivement, une hiérarchie de lignes 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
    14
    15
    16
    17
    18
    class BaseGraph
    class BaseLine
    {
        public:
            // je ne m'intéresse qu'au problème lié aux graphes ;)
            virtual void accept(BaseGraph&) = 0;
    };
    class PlaneLine : public BaseLine
    {
        public:
            virtual void accept(BaseGraph & g){g.vist(*this);}
    }
    class FaultedLine  : public BaseLine
    {
        public :
            virtual void accept(BaseGraph & g){g.vist(*this);}
    };
    /* les autres types de lignes */
    et une hiérarchie de graphes 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
    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
    class BaseGraph
    {
        public:
           virutal ~BaseGraph()
           {
               /* faudra sans doute réfléchir à la politique de gestion des
                * ressources
                */
           }
           void addItem(BaseLine * b){tab.push_back(b);}
           virtual void visit(PlaneLine &) = 0;
           virtual void visit(FaultedLine  &) = 0; 
           /* sans oublier les autres types de lignes */
           void visitAll()
           {
                struct Helper
                {
                    Helper(Visitor & v):v(v){}
                    Visitor v;
                    void operator()(Base* b)
                    {
                        b->accept(v);
                    }
                };
                 Helper h(*this);
                 for_each(tab.begin(),tab.end(), h);
           }
        private:
            std::vector<Base*> tab;
    };
    class GraphForIt : public BaseGraph
    {
        public:
           virtual void visit(PlaneLine &) {/* ce qui va bien */}
           virtual void visit(FaultedLine  &) {/* ce qui va bien */}
           /* sans oublier les autres types de lignes */
    };
    class GraphForThat : public BaseGraph
    {
        public:
           virtual void visit(PlaneLine &) {/* ce qui va bien */}
           virtual void visit(FaultedLine  &) {/* ce qui va bien */}
           /* sans oublier les autres types de lignes */
    };
    // et tous les autres graphes
    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

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2006
    Messages : 620
    Points : 453
    Points
    453
    Par défaut
    Salut Koala,

    Merci pour tes suggestions

    Je vais méditer tout ça

    Marc

Discussions similaires

  1. [JMS] Question de design
    Par El Saigneur dans le forum Java EE
    Réponses: 2
    Dernier message: 30/09/2008, 17h58
  2. Question de design
    Par hpavavar dans le forum Hibernate
    Réponses: 0
    Dernier message: 06/08/2008, 11h46
  3. Question de design
    Par Dohmaker dans le forum ASP.NET
    Réponses: 3
    Dernier message: 24/09/2007, 19h29
  4. Question de design?
    Par Jayceblaster dans le forum Delphi
    Réponses: 9
    Dernier message: 06/06/2006, 19h38
  5. [Struts] question de design
    Par mlequim dans le forum Struts 1
    Réponses: 4
    Dernier message: 26/10/2005, 12h27

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