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 :

[Conception] Metaclass-Regles parametrees


Sujet :

C++

  1. #1
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2003
    Messages
    224
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 224
    Par d�faut [Conception] Metaclass-Regles parametrees
    Bonjour,

    J'ai un gros probl�me de conception. Je le met dans C++ car je dois le r�soudre en C++.

    J'ai des regles types, appel�es RulesType qui ont comme propri�t�s:
    - un ID
    - un Nom
    - Des parametres Generiques(liste de parametres possibles)
    - Un resultat generiques (liste de resultat possible)
    - L'action de la r�gle en fonction des parametres et du resultat

    A partir de ces RulesType j'ai des Rules qui ont comme propri�t�s:
    - Un ID
    - un Nom
    - Des parametres sp�cifiques(pris parmis les resultats generiques de RulesType


    Chaque Rules d�pend d'un RulesType. Je peux avoir n Rules par RulesType.
    Et je peux avoir m RulesType diff�rents avec des parametres differents et des resultats differents.
    De plus, il me faut un RulesManager qui gerent l'ensemble de mes RulesType (pour les lister en fait).
    Il faut que je puisse instancier des Rules en fonction des RulesType associ�s (en gros mettre les bons parametres).

    Ou j'en suis:
    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
    // RuleTest.cpp : Defines the entry point for the console application.
    //
     
    #include <iostream>
    #include <map>
    #include <string>
    #include "stdafx.h"
     
    class RuleType{
    public:
        RuleType(int anId, std::string aName): id (anId), name (aName) {}
    protected:
        int id;
        std::string name;
     
    protected:
        RuleType();
        static std::map< int, RuleType*> rules;
     
    public:
        virtual int getID() {return id;}
        virtual std::string getName() {return name;}
        static void insertRule(int i, RuleType* rule) {rules[i] = rule;}
        static RuleType * getRule(int i) {return rules[i];}
    };
     
    std::map<int, RuleType*> RuleType::rules;
     
     
    class Rule1: public RuleType{
    public:
        Rule1(int anId, std::string aName): RuleType(anId, aName) {}
     
    private:
        Rule1();
        int idRule;
     
    public:
        int performRule(int i) {return i;}
    };
     
    class Rule2: public RuleType{
    public:
        Rule2(int anId, std::string aName): RuleType(anId, aName) {}
     
    private:
        Rule2();
        int idRule;
     
    public:
        std::string performRule(std::string str) {return str;}
    };
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        Rule1 * rule1 = new Rule1(1, "Rule1");
        Rule2 * rule2 = new Rule2(2, "Rule2");
        RuleType::insertRule(rule1->getID(), rule1);
        RuleType::insertRule(rule2->getID(), rule2);
     
        Rule1 * ruletmp1 = static_cast< Rule1 * > (RuleType::getRule(1));
        std::cout << "Rule1: " << ruletmp1->performRule(1) << std::endl;
     
        Rule2 * ruletmp2 = static_cast< Rule2 * > (RuleType::getRule(2));
        std::cout << "Rule2: " << ruletmp2->performRule("Rule2") << std::endl;
     
        int i;
        std::cin >> i;
    	return 0;
    }
    La class RuleManager est a la fois mon RuleManager et d�finit les parametres de base d'une Rules.
    Rule1 et Rule2 sont des RulesType differents (leur fonction performRule est differentes)
    Mon probleme est que je dois faire un static_cast et je trouve pas ca tr�s beau.


    Des id�es?

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

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    Ce que je ferais, c'est cr�er une classe abstraite - nommons la "Parametre" pour la cause - qui s'occupe simplement de g�rer... les param�tres.

    Elle ressemblerait �
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Parametre
    {
        public:
            Parametre(Parametre * n=0);
            virtual ~Parametre();
            Parametre* next(){return m_next;}
            virtual bool evaluate() =0 const; /* le type de retrour est à réfléchir... 
                                               * un retour  co-variant pourrait être le 
                                               * bienvenu :D
                                                */
        private:
            Parametre* m_next;
    };
    Elle serait impl�ment�e sous une forme proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    Parametre::Parametre(Parametre * n): m_next(n)
    {
    }
    Parametre::~Parametre()
    {
    }
    Si tu veux en restreindre l'usage, rien ne t'emp�che d'en faire une classe imbriqu�e dans ta classe RuleType .

    Tu pourrais alors faire d�river cette classe en diff�rents param�tres concrets qui impl�menteraient la m�thode virtuelle pure evaluate (on va dire, pour les besoins de l'exemple, que tu la fait d�river en P1, P2 et P3 ).

    Ta classe RuleType prendrait alors la forme 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
    class RuleType
    {
        public:
            RuleType(size_t, const std::string&, Parametre* p=0
            /*éventuellement */ RuleType* next=0);
            ~RuleType();
            bool isVerified() const; /* ici aussi, on peut réfléchir à un autre type
                                      * de retour ;)
                                      */
            size_t id() const{return m_id;}
            const std::string& name() const {return m_name;}
            /*si une regle doit pouvoir appeler une autre règle */
            RuleType* nextRule(){return m_next;}
            void setNextRule(RuleType* n){m_next=n;}
        private:
            size_t m_id;
            std::string m_name;
            Parametre* m_p;
            /*si une regle doit pouvoir appeler une autre règle */
            RuleType* m_next;
    };
    et l'impl�mentation des m�thodes serait de l'ordre 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
    RuleType::RuleType(const sd::string& i, const std::string& n, Parametre* p)
             :m_id(i),m_name(n),m_p(p),m_next(0)
    {
    }
    RuleType::~RuleType()
    {
        /*chaque règle est responsable de la destruction de ses paramètres*/
     
        while(m_p)
        {
            Param* t=m_p->next();
            delete m_p;
            m_p=t;
        }
        /* mais, par contre, ce sera au RuleManager de s'occuper de la 
         * destructions des règles, y compris de celle qui doit suivre :D
         */
    }
    bool RuleType::isVerified() const
    {
        /* on commence par déterminer si la regle est suivie en fonction
         * de ses parametres... par défaut, nous considérerons que c'est le cas
         */
        bool ret= true;
        Parametre * tmp=m_p;
        while(tmp && ret)
        {
            /* si un parametre n'est pas correctement évalué, la règle n'est
             * pas respectée :D
             */
            ret=ret&tmp->evaluate();
            ret=ret->next();
        }
        /*reste à savoir si une regle suit celle-ci, et à l'évaluer,si c'est
         * nécessaire je considère ici qu'il est inutile d'évaluer la règle
         * suivante si celle en cours n'est pas vérifiée :D
         */
        if(ret && m_next)
            return ret&m_next->isVerified();
        return ret;
    }
    Tu sera au final en mesure de cr�er une r�gle sous la forme de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    RuleType r(1,"LaRegle", new P1("lavaleur de p1", 
                            new P2 (1836, 
                            new P3(3.1415926)));
    en �tant libre du nombre de param�tre � lui passer

    Quand tu veux voir si une r�gle est v�rifi�e au d�part de ton RuleManager, il te "suffira" de s�lectionner la r�gle en question, et d'invoquer dessus la m�thode isVerified() pour que tous les param�tres (et les r�gles "suivantes" s'il y en a et si tu a d�cid� que cela pouvait se faire) soient �valu�es

    [EDIT]code de Parametre �dit�
    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 confirm�
    Profil pro
    Inscrit en
    F�vrier 2003
    Messages
    224
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 224
    Par d�faut
    Merci de ta reponse. Mais malheureusement c'est un poil plus compliqu�.

    virtual bool evaluate() =0 const;
    *je ne peux pas faire ca, car evaluate prend differents parametres suivant le "Type" de parametre et peut avoir des types de retour differents.

    Le code est pas super propre vu que je fais mes tests, mais c'est l'id�e.
    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
    class Parameter{
    public:
        Parameter(std::string aName, int idOp): name (aName), idOperator (idOp) {}
    protected:
        Parameter()  {}
        std::string name;
        int idOperator;
     
     
    public:
        std::string getName() {return name;}
    };
     
    enum ParameterIntOperators{
        equal,
        less,
        more
    };
     
    class ParameterInt: public Parameter {
    public:
        ParameterInt(std::string aName, int idOp, int anIdValue): Parameter(aName, idOp), idValue (anIdValue) {}
     
        bool getResult(int number) {
            if (idOperator == equal) {return number == idValue;}
            if (idOperator == less) {return number < idValue;}
            if (idOperator == more) {return number > idValue;}
            return false;
        }
    private:
            int idValue;
    };
     
    enum ParameterBenchOperators{
        bench,
        Hmin
    };
     
    class ParameterBench: public Parameter {
    public:
        ParameterBench(std::string aName, int idOp, int anIdValue): Parameter(aName, idOp), idValue (anIdValue) {}
     
        int getResult(int bench, int pos, int hmin = 0, int Hmax = 0, int Hr = 0) {
            if (idOperator == bench) {return bench + pos;}
            if (idOperator == Hmin) {return hmin + Hmax + Hr;}
            return 0;
        }
    private:
            int idValue;
    };
     
    enum ParameterStringOperators{
        toto,
        tata
    };
     
    class ParameterString: public Parameter {
    public:
        ParameterString(std::string aName, int idOp, std::string anIdValue): Parameter(aName, idOp), idValue (anIdValue) {}
     
        std::string getResult(std::string exemple) {
            if (idOperator == toto) {return exemple + idValue;}
            if (idOperator == tata) {return exemple + "tata" +idValue;}
            return "";
        }
    private:
        std::string idValue;
     
    };

    Ensuite une regle ne peut suivre une regle, elles sont toutes independantes les une des autres pour l execution.
    Mes regles me permettent en fait de faire des calculs precis, une regle pouvant me retourner une date, une autre pouvant me retourner un entier, une autre une chaine de caractere.
    En gros je dois melanger du lard et du cochon dans une structure coherente

    mon code entier pour l instant:
    Il represente bien ce que je veux faire. Les deux fonctions qui me posent problemes et qui m obligent a faire des choses pas bien sont getResult(..) des classes Parameter et performRule(..) des class Rule.

    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
    // RuleTest.cpp : Defines the entry point for the console application.
    //
     
    #include <iostream>
    #include <map>
    #include <string>
    #include "stdafx.h"// RuleTest.cpp : Defines the entry point for the console application.
     
    class Parameter{
    public:
        Parameter(std::string aName, int idOp, int anIdValue): name (aName), idOperator (idOp), idValue (anIdValue) {}
    protected:
        Parameter()  {}
        std::string name;
        int idOperator;
        int idValue;
     
    public:
        std::string getName() {return name;}
    };
     
    enum ParameterIntOperators{
        equal,
        less,
        more
    };
     
    class ParameterInt: public Parameter {
    public:
        ParameterInt(std::string aName, int idOp, int anIdValue): Parameter(aName, idOp, anIdValue) {}
     
        bool getResult(int number) {
            if (idOperator == equal) {return number == idValue;}
            if (idOperator == less) {return number < idValue;}
            if (idOperator == more) {return number > idValue;}
            return false;
        }
    };
     
    enum ParameterBenchOperators{
        bench,
        Hmin
    };
     
    class ParameterBench: public Parameter {
    public:
        ParameterBench(std::string aName, int idOp, int anIdValue): Parameter(aName, idOp, anIdValue) {}
     
        int getResult(int bench, int posOam, int hmin = 0, int Hmax = 0, int Hr = 0) {
            if (idOperator == bench) {return bench + posOam;}
            if (idOperator == Hmin) {return hmin + Hmax + Hr;}
            return 0;
        }
     
     
    };
     
    class RuleManager{
    public:
        RuleManager(int anId, std::string aName): id (anId), name (aName) {}
    protected:
        int id;
        std::string name;
        std::map < int, Parameter* > parameters;
     
    protected:
        RuleManager();
        static std::map< int, RuleManager*> rules;
     
    public:
        virtual int             getID()                                 {return id;}
        virtual std::string     getName()                               {return name;}
        virtual void            insertParam(int i, Parameter* param)    {parameters[i] = param;}
        virtual Parameter*      getParam(int i)                         {return parameters[i];}
        static void             insertRule(int i, RuleManager* rule)    {rules[i] = rule;}
        static RuleManager *    getRule(int i)                          {return rules[i];}
    };
     
    std::map<int, RuleManager*> RuleManager::rules;
     
    class Rule1: public RuleManager{
    public:
        Rule1(int anId, std::string aName): RuleManager(anId, aName) {}
     
    private:
        Rule1();
        int idRule;
     
    public:
        int performRule(int i) {
            int res = i;
            int bench_ = 10;
            int posOam_ = 15;
            int hmin_ = 5;
            int hmax_ = 6;
            if (static_cast<ParameterInt*>(getParam(1))->getResult(bench_)) {
                res += 10;
            }
            if (static_cast<ParameterInt*>(getParam(2))->getResult(bench_)) {
                res += 10;
            }
            res += static_cast<ParameterBench*>(getParam(3))->getResult(bench_, posOam_);
            return res;
        }
    };
     
    class Rule2: public RuleManager{
    public:
        Rule2(int anId, std::string aName): RuleManager(anId, aName) {}
     
    private:
        Rule2();
        int idRule;
     
    public:
        std::string performRule(std::string str) {return str;}
    };
     
    int _tmain(int argc, _TCHAR* argv[])
    {
        Rule1 * rule1 = new Rule1(1, "Rule1");
        Rule2 * rule2 = new Rule2(2, "Rule2");
        RuleManager::insertRule(rule1->getID(), rule1);
        RuleManager::insertRule(rule2->getID(), rule2);
        rule1->insertParam(1, new ParameterInt("int", equal, 10));
        rule1->insertParam(2, new ParameterInt("int", less, 15));
        rule1->insertParam(3, new ParameterBench("bench", bench, 20));
     
        Rule1 * ruletmp1 = static_cast< Rule1 * > (RuleManager::getRule(1));
        std::cout << "Rule1: " << ruletmp1->performRule(1) << std::endl;
     
        Rule2 * ruletmp2 = static_cast< Rule2 * > (RuleManager::getRule(2));
        std::cout << "Rule2: " << ruletmp2->performRule("Rule2") << std::endl;
     
        int i;
        std::cin >> i;
        return 0;
    }
    PS: je sais, la gestion de la memoire est inexistante, mais bon c'est des tests, donc jai la flemme de tout faire bien et propre.

    Merci de ton aide en tout cas.

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

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par escafr Voir le message
    Merci de ta reponse. Mais malheureusement c'est un poil plus compliqu�.


    *je ne peux pas faire ca, car evaluate prend differents parametres suivant le "Type" de parametre et peut avoir des types de retour differents.
    Comme je l'ai indiqu� dans le code, tu peux sans doute envisager un retour co-variant pour evaluate... Cela n�cessite �videmment d'avoir une arborescence de "retour" coh�rente, avec un interface permettant le polymorphisme dessus

    Ici, l'id�e est de se dire "j'�value un parametre, et je renvoi le r�sultat correspondant au type de param�tre �valu�"

    Rien ne t'interdit non plus de rajouter des m�thodes "qui vont bien", voire, de pr�voir une surcharge pour la m�thode �valuate

    L'id�e �tant qu'un parametre donn� ne soit responsable que d'une chose: son
    <snip>
    Ensuite une r�gle ne peut suivre une regle, elles sont toutes independantes les une des autres pour l execution.
    comme indiqu� dans les commentaires (il faut toujours lire les commentaires, je les met pour indiquer les variantes envisageable), je ne t'indiquais qu'une optique possible...

    Libre � toi de supprimer toute r�f�rence � "une r�gle suivante" dans le code
    Mes regles me permettent en fait de faire des calculs precis, une regle pouvant me retourner une date, une autre pouvant me retourner un entier, une autre une chaine de caractere.
    En gros je dois melanger du lard et du cochon dans une structure coherente
    Et alors, ou est le probl�me
    tu cr�e une interface pour "les parametres" et une interface pour "le type de calcul"

    En rendant la m�thode isVerified(), nomm�e ainsi parce que, pour moi une r�gle est plutot le genre de truc pour lequel on r�pond � la question "la r�gle est-elle suivie", mais que l'on pourrait tr�s bien nommer calculate() virtuelle, rien ne t'empeche de cr�er une arborescence sur base de cette classe...

    Tu as donc deux arborescences bien distinctes dont l'une te permet de dire "je veux faire ceci", et l'autre te permet de dire "et voila avec quoi je veux le faire"

    Ca pourrait tout aussi bien prendre une forme proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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
     
    class Operation
    {
        public:
            Operation(Operation* n =0):m_next(0){}
            virtual ~Operation(){}
            Operation* next() {return m_next;}
            virtual double calculate(double) =0;
            /* à n'utiliser que pour les classes dérivant de Calcul */
            void setNext(n){m_next=n;}
        private:
            Operation * m_next;
    };
    /* chaque opération contient l'opérande se trouvant à droite du signe */
    class Add:public Operation
    {
        public:
            Add(double rval, Operation* n = 0):Operation(n), m_val(rval){}
            virtual ~Add(){}
            virtual double calculate(double lval)
            {return lval+m_val;}
        private:
            double m_val;
    };
    class Multiply:public Operation
    {
        public:
            Multiply(double rval, Operation* n = 0):Operation(n), m_val(rval){}
            virtual ~Multiply();
            virtual double calculate(double lval)
            {return lval*m_val;}
        private:
            double m_val;
    };
    class Substract:public Operation
    {
        public:
            Substract(double rval, Operation* n = 0):Operation(n), m_val(rval){}
            virtual ~Substract();
            virtual double calculate(double lval)
            {return lval-m_val;}
        private:
            double m_val;
    };
    class Divide:public Operation
    {
        public:
            Divide(double rval, Operation* n = 0):Operation(n), m_val(rval){}
            virtual ~Substract();
            virtual double calculate(double lval)
            {   
                 /*idéalement, il faudrait sortir une erreur si division par 0 ;) */
                 return lval/m_val;
            }
        private:
            double m_val;
    };
    et, tu aurais dune classe "Calcul" qui prendrait la forme 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
     
    class Calcul
    {
        public: 
            Calcul(double first, Operation* op= 0):m_first(first), m_op(op){}
            ~Calcul(){/*suppression des opérations ;) */}
            virtual double evaluate() const;
            {
                 double ret=m_first;
                 Operation* temp=m_op;
                 while(temp)
                 {
                     temp->calculate(ret);
                     temp=temp->next;
                 }
                 return ret;
            }
        protected:
            Operation m_op;
        private:
            double m_first;
    };
    Bon, bien sur, j'ai pass� les id, les nom et d'autres trucs, inutiles � ma d�monstration...
    Mais tu pourrais tr�s bien alors envisager de la d�river en
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class TwoOpsCalcul : public Calcul
    {
        public:
            TwoOpsCalcul(double first, Operation* fop, Operation* sop)
                Calcul(first, fop)
            {
                assert(fop!=0);
                assert(sop!=0);
                fop->setNext(sop);
            }
            virtual ~TwoOpsCalcul(){}
     
    }
    qui te permettra de cr�er un calcul du genre de 2+4*5 (et tu peux t'amuser � cr�er autan de classe que tu veux avec autant d'op�rations que tu veux sur le m�me principe )
    mon code entier pour l instant:
    Il represente bien ce que je veux faire. Les deux fonctions qui me posent problemes et qui m obligent a faire des choses pas bien sont getResult(..) des classes Parameter et performRule(..) des class Rule.[/QUOTE]
    La m�thode performRule, c'est en fait la m�thode evaluate pr�sent�e plus haut

    Maintenant, il est peut etre utile de pr�voir une classe Resultat, que tu ferai d�river en plusieurs autres classe, afin de permettre le retour co-variant

    Une des id�es principales en Orient� objet, c'est la d�l�gation des responsabilit�s: Si une de tes classe est responsable de plus d'une chose, c'est sans doute qu'elle a trop de responsabilit�s:

    Ici, tu as quatre responsabilit�s distinctes d�j� identifi�es, qui portent respectivement sur
    • le r�sultat
    • l'op�ration
    • le calcul
    • la gestion des calculs


    Tu dois donc avoir au minimum 4 classes: une pour chacune de ces responsabilit�s.

    Pour trois d'entre-elles, (le r�sultat, l'op�ration et le calcul), tu dois sans doute envisager un arbre d'h�ritage s�par� (un calcul n'a rien � voir avec les diff�rents types d'op�ration qu'il doit effectuer, une op�ration n'a rien � voir avec les diff�rents type de r�sultat qu'il doit obtenir), de mani�re � pouvoir profiter au mieux du polymorphisme et du retour co-variant en cas de besoin.

    De cette mani�re, si un jour tu te rend compte qu'il faut un nouveau type de r�sultat, tu pourra te contenter de le cr�er sans devoir aller modifier le code des op�rations.

    Par contre, il est fort vraisemblable que tu doive aussi (parce que c'est sans doute la raison pour laquelle ce nouveau type de r�sultat est n�cessaire), cr�er une nouveau type d'op�ration, voire, un nouveau type de calcul...

    Mais l'avantage r�sidera dans le fait que tous les type d'op�ration et tous les types de calcul existants ne devront absolument pas �tre modifi�s

    Le diagrame UML de ton ensemble ressemblerait � celui ci-joint (fait en quatri�me vitesse )

    Ainsi, Resultat s'occupera de g�rer le type et la valeur du r�sultat d'une op�ration, une op�ration se contentera de cr�er le r�sultat attendu, un calcul s'occupera d'appeler les diff�rentes op�rations n�cessaires (bien qu'il renvoie lui aussi un r�sultat), et le RuleManager s'occupera de g�rer les diff�rents calculs que l'on peut lui demander
    <sniped code>

    PS: je sais, la gestion de la memoire est inexistante, mais bon c'est des tests, donc jai la flemme de tout faire bien et propre.
    Ca, c'est vraiment pas bien ...

    M�me pour des essais, il faut veiller � ce que ton code soit correct
    Images attach�es Images attach�es  
    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

  5. #5
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2003
    Messages
    224
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 224
    Par d�faut
    ouah.. j'en demandais pas autant. Merci..

    Alors le retour covariant je connaissais pas du tout. C'est plutot sympa dans l'esprit mais je pense que c'est un poil trop compliquer les choses.

    Apr�s r�flexion, et discussion avec un coll�gue, je vais m'orienter vers une solution bcp plus simple

    En fait le probl�me fondamental que j'avais, �tait de dissocier la description de mes regles de l'utilisation de mes regles. De meme pour mes parametres.
    L'id�e est donc de dissocier les deux.
    Une regle type contient une description de regle et une description de parametre.
    Une regle contient des parametres. Je parametre mes regles en fonction de leur description. Simple efficace.

    Je reviendrai avec la facon d'implementer tout ca bientot

  6. #6
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2003
    Messages
    224
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 224
    Par d�faut
    Bonsoir,

    Me revoila avec une interogation sur le retour covariant


    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
    class Rule{
    protected:
        Rule() {ruleDesc = NULL;}
    public:
        Rule(RuleDescription* ruleDesc):  ruleDesc(ruleDesc) {}
        virtual ~Rule(){
            while (!paramDesc.empty()){
                delete paramDesc.begin()->second;
                paramDesc.erase(paramDesc.begin());
            }
        }
    
        void insertParam(int i, ParameterDescription* param) {paramDesc[i] = param;}
    
        int getNumberParam() {return paramDesc.size();}
        std::string getNameParam(int i) {return paramDesc[i]->getName();}
        int getOperatorParam(int i) {return paramDesc[i]->getOperator();}
        std::string getOperatorValue(int i) {return paramDesc[i]->getValue();}
    
        void print() {
            std::cout << "Listing Params for rule:" << ruleDesc->getName() << std::endl;
            for(std::map <int, ParameterDescription*>::const_iterator i = paramDesc.begin(); i != paramDesc.end(); i++){
                i->second->print();
            }
            std::cout << "----" << std::endl;
        }
        virtual int getScope(int i) = 0;
        virtual Rule* getRule(int i)  = 0;
    
    protected:
        RuleDescription* ruleDesc;
        std::map <int, ParameterDescription*> paramDesc;
    
    };
    
    class RuleBackToBench: public Rule{
    public:
        RuleBackToBench( RuleDescription* ruleDesc): Rule( ruleDesc) {}
    
        static RuleBackToBench* getRule(int i) {
            std::stringstream strname;
            std::stringstream strdate;
            // Recherche Scope et recuperation bon RuleDescription
            RuleBackToBench* ruleB = new RuleBackToBench(RuleDescription::getRule(getScope(i)));
            for (int i = 0; i < 5; i++){
                ParameterDescription* tmp = NULL;
                strname.str("");
                strdate.str("");
                strname << "NameParam" << i;
                strdate << "Value" << i;
                tmp = new ParameterDescription(i, strname.str(), i%2, strdate.str());
                ruleB->insertParam(i, tmp);
            }
            return ruleB;
        }
    
        static int getScope(int i) {return i;}
    };
    
    class RuleSettlement: public Rule{
    public:
        RuleSettlement( RuleDescription* ruleDesc): Rule( ruleDesc) {}
    
        static RuleSettlement* getRule(int i) {
            std::stringstream strname;
            std::stringstream strdate;
            // Recherche Scope et recuperation bon RuleDescription
            RuleSettlement* ruleB = new RuleSettlement(RuleDescription::getRule(getScope(i)));
            for (int i = 0; i < 5; i++){
                ParameterDescription* tmp = NULL;
                strname.str("");
                strdate.str("");
                strname << "NameParam" << i;
                strdate << "Value" << i;
                tmp = new ParameterDescription(i, strname.str(), i%2, strdate.str());
                ruleB->insertParam(i, tmp);
            }
            return ruleB;
        }
    
        static int getScope(int i) {return i;}
    };

    faisant partie du code plus vaste:
    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
    // RuleTest2.cpp : Defines the entry point for the console application.
    //
     
    #include "stdafx.h"
    #include <string>
    #include <iostream>
    #include <sstream>
    #include <map>
     
    class Rule;
     
    class RuleTypeDescription{
    private:
        RuleTypeDescription();
    public:
        RuleTypeDescription(int id, std::string name, int nature, std::string creaDate, std::string doc): id(id), name(name), nature(nature),creaDate(creaDate), doc(doc) {}
     
        static void insertDesc(int i, RuleTypeDescription* obj) {rulesTypeDesc[i] = obj;}
     
        int getNature() {return nature;}
    private:
        int id;
        std::string name;
        int nature;
        std::string creaDate;
        std::string doc;
     
        static std::map <int, RuleTypeDescription*> rulesTypeDesc;
     
    public:
        void printRule() const{
            std::cout << id << ":" << name << ":" << nature << ":" << creaDate << doc << std::endl;
        }
     
        static void listRules() {
            std::cout << "Listing RuleType:" << std::endl;
            for(std::map <int, RuleTypeDescription*>::const_iterator i = rulesTypeDesc.begin(); i != rulesTypeDesc.end(); i++){
                i->second->printRule();
            }
            std::cout << "----" << std::endl;
        }
        static void kill() {
            while (!rulesTypeDesc.empty()){
                delete rulesTypeDesc.begin()->second;
                rulesTypeDesc.erase(rulesTypeDesc.begin());
            }
        }
        static RuleTypeDescription* getRuleType(int i) {return rulesTypeDesc[i];}
    };
     
    std::map <int, RuleTypeDescription*> RuleTypeDescription::rulesTypeDesc;
     
     
    class RuleDescription{
    private:
        RuleDescription();
    public:
        RuleDescription(int id, std::string name, std::string scope, RuleTypeDescription * ruleType): id(id), name(name), scope(scope),ruleType(ruleType)  {}
     
        static void insertDesc(int i, RuleDescription* obj) {rulesDesc[i] = obj;}
     
        std::string getName() {return name;}
    private:
        int id;
        std::string name;
        std::string scope;
        std::string creaDate;
        std::string startDate;
        std::string endDate;
        std::string user;
     
        RuleTypeDescription * ruleType;
     
        static std::map <int, RuleDescription*> rulesDesc;
     
    public:
        void printRule() const {
            std::cout << id << ":" << name << ":" << ruleType->getNature() << ":" << scope << ":" << creaDate << std::endl;
        }
     
        static void listRules() {
            std::cout << "Listing Rules:" << std::endl;
            for(std::map <int, RuleDescription*>::const_iterator i = rulesDesc.begin(); i != rulesDesc.end(); i++){
                i->second->printRule();
            }
            std::cout << "----" << std::endl;
        }
        static void kill() {
            while (!rulesDesc.empty()){
                delete rulesDesc.begin()->second;
                rulesDesc.erase(rulesDesc.begin());
            }
        }
     
        static RuleDescription* getRule(int i) {return rulesDesc[i];}
    };
     
    std::map <int, RuleDescription*> RuleDescription::rulesDesc;
     
    class ParameterDescription{
    public:
        ParameterDescription(int id, std::string name, int op, std::string value): id (id), name (name), idoperator(op), value(value) {}
     
    private:
        ParameterDescription();
        int id;
        std::string name;
     
        int idoperator;
        std::string value;
    public:
        std::string getName() {return name;}
        int getOperator() {return idoperator;}
        std::string getValue() {return value;}
     
        void print() {std::cout << name << ":" << idoperator << ":" << value << std::endl;}
     
    };
     
    class Rule{
    protected:
        Rule() {ruleDesc = NULL;}
    public:
        Rule(RuleDescription* ruleDesc):  ruleDesc(ruleDesc) {}
        virtual ~Rule(){
            while (!paramDesc.empty()){
                delete paramDesc.begin()->second;
                paramDesc.erase(paramDesc.begin());
            }
        }
     
        void insertParam(int i, ParameterDescription* param) {paramDesc[i] = param;}
     
        int getNumberParam() {return paramDesc.size();}
        std::string getNameParam(int i) {return paramDesc[i]->getName();}
        int getOperatorParam(int i) {return paramDesc[i]->getOperator();}
        std::string getOperatorValue(int i) {return paramDesc[i]->getValue();}
     
        void print() {
            std::cout << "Listing Params for rule:" << ruleDesc->getName() << std::endl;
            for(std::map <int, ParameterDescription*>::const_iterator i = paramDesc.begin(); i != paramDesc.end(); i++){
                i->second->print();
            }
            std::cout << "----" << std::endl;
        }
        virtual int getScope(int i) = 0;
        virtual Rule* getRule(int i)  = 0;
     
    protected:
        RuleDescription* ruleDesc;
        std::map <int, ParameterDescription*> paramDesc;
     
    };
     
    class RuleBackToBench: public Rule{
    public:
        RuleBackToBench( RuleDescription* ruleDesc): Rule( ruleDesc) {}
     
        static RuleBackToBench* getRule(int i) {
            std::stringstream strname;
            std::stringstream strdate;
            // Recherche Scope et recuperation bon RuleDescription
            RuleBackToBench* ruleB = new RuleBackToBench(RuleDescription::getRule(getScope(i)));
            for (int i = 0; i < 5; i++){
                ParameterDescription* tmp = NULL;
                strname.str("");
                strdate.str("");
                strname << "NameParam" << i;
                strdate << "Value" << i;
                tmp = new ParameterDescription(i, strname.str(), i%2, strdate.str());
                ruleB->insertParam(i, tmp);
            }
            return ruleB;
        }
     
        static int getScope(int i) {return i;}
    };
     
    class RuleSettlement: public Rule{
    public:
        RuleSettlement( RuleDescription* ruleDesc): Rule( ruleDesc) {}
     
        static RuleSettlement* getRule(int i) {
            std::stringstream strname;
            std::stringstream strdate;
            // Recherche Scope et recuperation bon RuleDescription
            RuleSettlement* ruleB = new RuleSettlement(RuleDescription::getRule(getScope(i)));
            for (int i = 0; i < 5; i++){
                ParameterDescription* tmp = NULL;
                strname.str("");
                strdate.str("");
                strname << "NameParam" << i;
                strdate << "Value" << i;
                tmp = new ParameterDescription(i, strname.str(), i%2, strdate.str());
                ruleB->insertParam(i, tmp);
            }
            return ruleB;
        }
     
        static int getScope(int i) {return i;}
    };
     
    int _tmain(int argc, _TCHAR* argv[])
    {    
        std::stringstream strname;
        std::stringstream strdate;
        std::stringstream strdoc;
        for (int i = 0; i < 5; i++) {
            RuleTypeDescription* tmp = NULL;
            strname.str("");
            strdate.str("");
            strdoc.str("");
            strname << "Name" << i;
            strdate << "Today" << i;
            strdoc << "Doc" << i;
            tmp = new RuleTypeDescription(i, strname.str(),i, strdate.str(), strdoc.str());
            RuleTypeDescription::insertDesc(i, tmp);
        }
        RuleTypeDescription::listRules();
     
        for (int i = 0; i < 10; i++) {
            RuleDescription* tmp = NULL; 
            strname.str("");
            strdate.str("");
            strdoc.str("");
            strname << "NameRule" << i;
            strdate << "Scope" << i;
            tmp = new RuleDescription(i, strname.str(), strdate.str(), RuleTypeDescription::getRuleType(i%3));
            RuleDescription::insertDesc(i, tmp);
        }
        RuleDescription::listRules();
     
        RuleBackToBench* ruleB = RuleBackToBench::getRule(0);
        ruleB->print();
        delete ruleB;
        ruleB = RuleBackToBench::getRule(1);
        ruleB->print();
        delete ruleB;
     
        RuleSettlement* ruleS = RuleSettlement::getRule(2);
        ruleS->print();
        delete ruleS;
     
        RuleTypeDescription::kill();
        RuleDescription::kill();
     
        int i;
        std::cin >> i;
        return 0;
    }
    message d'erreur:
    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
    1>c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(159) : warning C4526: 'RuleBackToBench::getRule' : static member function cannot override virtual function 'Rule *Rule::getRule(int)'
    1>        override ignored, virtual function will be hidden
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(147) : see declaration of 'Rule::getRule'
    1>c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(176) : warning C4526: 'RuleBackToBench::getScope' : static member function cannot override virtual function 'int Rule::getScope(int)'
    1>        override ignored, virtual function will be hidden
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(146) : see declaration of 'Rule::getScope'
    1>c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(163) : error C2259: 'RuleBackToBench' : cannot instantiate abstract class
    1>        due to following members:
    1>        'int Rule::getScope(int)' : is abstract
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(146) : see declaration of 'Rule::getScope'
    1>        'Rule *Rule::getRule(int)' : is abstract
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(147) : see declaration of 'Rule::getRule'
    1>c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(183) : warning C4526: 'RuleSettlement::getRule' : static member function cannot override virtual function 'Rule *Rule::getRule(int)'
    1>        override ignored, virtual function will be hidden
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(147) : see declaration of 'Rule::getRule'
    1>c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(200) : warning C4526: 'RuleSettlement::getScope' : static member function cannot override virtual function 'int Rule::getScope(int)'
    1>        override ignored, virtual function will be hidden
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(146) : see declaration of 'Rule::getScope'
    1>c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(187) : error C2259: 'RuleSettlement' : cannot instantiate abstract class
    1>        due to following members:
    1>        'int Rule::getScope(int)' : is abstract
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(146) : see declaration of 'Rule::getScope'
    1>        'Rule *Rule::getRule(int)' : is abstract
    1>        c:\__gs\__testcpp\ruletest2\ruletest2\ruletest2.cpp(147) : see declaration of 'Rule::getRule'
    A priori tout est dit dans l erreur.
    Mais j'aurais voulu savoir si il n'etait pas possible de definir une fonction virtuel static abstraite A priori non, mais bon, je demande au cas ou...

  7. #7
    R�dacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supa�ro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activit� : Ing Supa�ro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par d�faut
    Mais j'aurais voulu savoir si il n'etait pas possible de definir une fonction virtuel static abstraite A priori non, mais bon, je demande au cas ou...
    L'abstraction impose la virtualit�. Et la virtualit� empeche la staticit�. La r�ciproque est vrai aussi (la staticit� empeche la virtualit�).

    En effet, une fonction virtuelle est choise au moment de l'ex�cution selon le type r�el de l'objet appellant. Or une le but d'une fonction statique est d'�tre appel� sans objet. D�s lors il est �vident qu'on ne peut pas mettre les 2 ensemble.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une tr�s bonne doc sur le C++ (en) Why linux is better (fr)

  8. #8
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2003
    Messages
    224
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 224
    Par d�faut
    make sens

    Merci.

  9. #9
    R�dacteur/Mod�rateur
    Avatar de JolyLoic
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Ao�t 2004
    Messages
    5 463
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 51
    Localisation : France, Yvelines (�le de France)

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

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 5 463
    Par d�faut
    Citation Envoy� par escafr Voir le message
    Mais j'aurais voulu savoir si il n'etait pas possible de definir une fonction virtuel static abstraite A priori non, mais bon, je demande au cas ou...
    Il m'est arriv� aussi d'avoir cette envie. L'exemple qui me vient en t�te est la g�n�ration d'un identifiant pour une classe (par exemple pour s�rialiser cette classe). On a deux cas d'utilisation : On veut lors de la s�rialisation retrouver la classe r�elle d'un objet (donc fonction virtuelle), mais on veut lors de la d�s�rialisation obtenir l'identifiant d'une classe sans avoir d'objet (statique).

    En fait, pos� ainsi, le probl�me a une solution toute simple :
    Faire deux fonctions, l'une statique, et l'autre virtuelle qui dans son impl�mentation appelle la statique.

    Je ne sais pas si c'est ce genre de cas qui t'as fait poser la question...
    Ma session aux Microsoft TechDays 2013 : D�velopper en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage � la d�couverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'h�sitez pas � me contacter.

  10. #10
    Membre confirm�
    Profil pro
    Inscrit en
    F�vrier 2003
    Messages
    224
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : F�vrier 2003
    Messages : 224
    Par d�faut
    Citation Envoy� par JolyLoic Voir le message

    Je ne sais pas si c'est ce genre de cas qui t'as fait poser la question...
    oui tout a fait

    La solution est de plus tr�s simple. Merci

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. [03] Regles de conception-default, legende,regles de validation
    Par xavsuderrone dans le forum Mod�lisation
    R�ponses: 4
    Dernier message: 01/02/2009, 00h14
  2. [Concept] M�tadatas ?
    Par melinda dans le forum D�cisions SGBD
    R�ponses: 5
    Dernier message: 10/11/2004, 11h56
  3. [Concept] R�plication
    Par melinda dans le forum D�cisions SGBD
    R�ponses: 4
    Dernier message: 31/03/2003, 17h29
  4. [Concept] Curseur cot� client et curseur cot� serveur
    Par freud dans le forum D�cisions SGBD
    R�ponses: 2
    Dernier message: 13/09/2002, 22h13
  5. [Concept] Stabilit� d'une base de donn�e
    Par lassmust dans le forum D�cisions SGBD
    R�ponses: 3
    Dernier message: 03/07/2002, 16h16

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