IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Interface de fonction avec signature variable


Sujet :

Langage C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Interface de fonction avec signature variable
    Hello,

    J'aimerais imposer à un ensemble de classes l'implémentation d'une fonction dont la signature varie selon la classe.

    Je suppose qu'il existe un pattern pour faire ça.
    Une proposition à me faire ?

    Merci.

  2. #2
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Qu'est-ce que tu peux imposer à tes classes? Sans sans moyen de pression, tu ne vas pas réussir.

    CRTP comme d'habitude?

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Qu'est-ce que tu peux imposer à tes classes? Sans sans moyen de pression, tu ne vas pas réussir.
    Il y a 16 classes filles. Les pointeurssur les instances sont stockées dans un conteneur, et la fameuse fonction est appelée de manière polymorphique par la suite.
    Mais il y a une telle variabilité entre les implémentations des fonctions, que je me retrouve avec 8 arguments. 2 sont systématiquement utilisés. En général, c'est plutôt 3, au maximum 5.
    C'est laid.

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    CRTP comme d'habitude?
    Avec le polymorphisme, c'est pour l'instant difficile. Il va falloir que je m'en débarrasse.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 637
    Par défaut
    Salut,

    En fait, il me semble qu'il y a, vraiment, un problème conceptuel dans ton histoire...

    Par définition, une fonction virtuelle est une fonction dont le comportement va s'adapter au type réel de l'objet au travers duquel elle est appelée.

    Mais, par définition, pour pouvoir redéfinir une fonction virtuelle, il faut que le nombre et le type de ses arguments soit stable :

    Si, au niveau de la classe de base, tu définis une fonction virtuelle prenant un seul int en argument, le fait de déclarer et de définir une fonction dont le nom est identique mais qui nécessite deux entiers en arguments dans une classe dérivée ne va absolument pas redéfinir le comportement de la première au sens polymorphique du terme : cela va juste créer, pour la classe dérivée, une nouvelle fonction dont le nom est identique, mais qui nécessite deux arguments (et dont le comportement pourra être redéfini au besoin par les classes qui dériveront de ta classe dérivée).

    Une des solutions consiste à déclarer, dans ta classe de base, ta fonction avec "le maximum de paramètres possibles" et à fournir une valeur par défaut pour les paramètres "qui ne sont pas forcément utilisés".

    Mais cela implique que:
    1. Pour chaque paramètre qui risque de ne pas être utilisé, il soit possible de définir une valeur qui puisse représenter un élément invalide
    2. Dans chaque (re)définition de la fonction, tu devras tester l'ensemble des paramètres "optionnels" pour t'assurer de leur (in)validité et donc savoir s'il respectent les conditions d'utilisation propres à la redéfinition du comportement.
    De plus, si un nombre de trois arguments est un nombre "correct" (on peut encore assez facilement se souvenir de l'ordre dans lequel il faut les passer), un nombre de cinq à huit arguments me semble pour le moins excessif, car on risque toujours de se tromper dans l'ordre des arguments et, s'ils sont de type compatible (des entiers par exemple), il devient assez facile de filer la mauvaise valeur à l'un d'eux, ce qui risque de fausser quelque peu les résultats

    Dés lors, je me demande si la solution (basée sur une approche purement OO) ne nous serait pas, une fois de plus, donnée par David Wheeler : ajouter une abstraction permettant de représenter une "liste d'arguments".

    L'idée de base serait -- peut être -- de créer une classe de base, mettons ArgumentList, qui serait transmise sous la forme d'une référence (éventuellement constante) à ta fonction virtuelle, qui serait dérivée en "spécialisations" permettant de représenter trois, quatre, cinq, six, sept ou huit arguments.

    Dans ce cas, le double dispatch risque de poser des problème, car il en faudrait deux : un premier pour récupérer le type réel de l'objet au départ duquel tu appelle la fonction virtuelle et l'autre pour récupérer le type réel de la liste d'arguments. Il est possible d'y arriver, mais une chose est sure, le patron de conception visiteur n'est absolument pas adapté à la manoeuvre

    Ceci dit, on déconseille généralement d'avoir recours aux transtypage (que ce soit static_cast ou dynamic_cast) afin de "downcaster" une référence (ou un pointeur) vers le type de base. Et ce conseil est tout ce qu'il y a de plus valide en première approche.

    La raison de se conseil est que, sinon, il est très facile de finir par se retrouver avec un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if( dynamic_cast<Type1*>(&param)){
    /* ... */
    }else if( dynamic_cast<Type2*>(&param)){
    /* ... */
    }else if( dynamic_cast<Type3*>(&param)){
    /* ... */
    }/* ... */
    else if( dynamic_cast<TypeN*>(&param)){
    /* ... */
    }
    qui ne sera absolument pas maintenable sur le long terme.

    En effet, un tel code aurait très facilement tendance à se "multiplier comme des petits pains", et toute tentative d'ajouter un nouveau type dérivé nécessiterait de modifier chaque apparition de ce code afin de prendre le nouveau type dérivé en compte.

    Par contre, si tu sais que la redéfinition de la fonction pour l'une de tes classes dérivées a besoin strictement de cinq arguments (et non de 4 ou de 6), et que tu peux donc essayer de transformer l'argument qu'elle reçoit dans un type particulier en étant sur que, si le transtypage ne fonctionne pas, c'est qu'il y a un problème, le transtypage peut te permettre d'éviter le recours à un double dispatch supplémentaire.

    A ce moment là, tu n'es plus dans une logique de sélection du type comme celle que met en oeuvre le code que je viens de montrer, mais bien dans une logique de vérification du type qui t'es transmis

    Tu pourrais donc parfaitement envisager d'avoir une hiérarchie de classes pour tes arguments 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
    23
    24
    25
    26
    27
    class ArgumentList{
        /* ... */
    };
    /* pour trois arguments */
    class ThreeArgumentList : public ArgumentList{
        public:
        Type1 arg1;
        Type2 arg2;
        Type3 arg3;
    };
    /* pour quatre arguments */
    class FourArgumentList : public ArgumentList{
        public:
        Type1 arg1;
        Type2 arg2;
        Type3 arg3;
        Type4 arg4;
    };
    /* ... */
    /* pour 8 arguments */
    class HeightArgumentList : public ArgumentList{
        public:
        Type1 arg1;
        Type2 arg2;
        /* ... */
        Type8 arg8;
    };
    d'un coté, et, de l'autre, ta hiérarchie de 16 classes 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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    class Base{
        public:
            virutal void foo(ArgumentList /* const */ &) = 0;
    };
    /* cette classe-ci a strictement besoin de trois arguments */
    class Derivee1 : public Base{
        public:
            void foo(ArgumentList /* const */ & args){
                ThreeArgumentList * real = dynamic_cast<ThreeArgumentList*>(&args);
                if(!real){
                    /* ... */
                }else{
     
                    /* ce n'est pas ce qu'on attendait, faut l'indiquer à l'utilisateur (ou
                     * au dévelopeur)
                     */
               }
            }
    }
    /* et celle-ci a strictement besoin de huit arguments */
    class DeriveeN : public Base{
        public:
            void foo(ArgumentList /* const */ & args){
                ThreeArgumentList * real = dynamic_cast<HeightArgumentList*>(&args);
                if(!real){
                    /* ... */
                }else{
     
                    /* ce n'est pas ce qu'on attendait, faut l'indiquer à l'utilisateur (ou
                     * au dévelopeur)
                     */
               }
            }
    }
    Dans un tel cas, le transtypage n'est peut être pas la meilleure solution (il faudrait comparer en terme de performances par rapport à un double dispatch classique), mais il reste malgré tout une alternative tout à fait valable
    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
    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
    Je suis pas sur de tout avoir compris avec ton histoire 8 paramètres mais tous ne servent pas.

    On pourrait avoir un bout de code (meme fictif) pour voir clairement la situation et ce que tu veux faire ?
    "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)

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Pour simplifier à l'extrême, disons que j'ai une classe Quadrilatère, avec les classes filles Rectangle et Carré. Des instances de chacune des classes filles sont stockées sous forme de pointeur dans un conteneur, et de manière polymorphique, je veux appeler une méthode Redimensionner(). Selon la classe sous-jacente, le nombre d'arguments nécessaire ne sera pas le même. Ma méthode, virtuelle, a donc 2 arguments, même si l'un d'enter eux ne sera pas utilisé dans le cas du carré.

    Il y clairement un problème de conception à la base, mais je ne peux pas complètement renverser la table.

    Bon, je vais prendre à présent du temps pour lire la réponse de koala01.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par koala01 Voir le message
    En fait, il me semble qu'il y a, vraiment, un problème conceptuel dans ton histoire...
    C'est là qu'est l'os, hélas.

    Pour le début de ton intervention, nous sommes biens d'accord.

    Pour la suite, le problème est que le code concerné est sensible aux performances. En fait, une partie des arguments serait regroupable par paires (les structures de données existent déjà). Je pourrais me retrouver avec 5 arguments plutôt que 8. Mais construire les objets prendrait du temps sans que cela ait un apport fonctionnel.

    Alors utiliser ajouter une indirection et utiliser du dynamic_cast...

    Je crois que je me repencherai dessus plus tard quand j'aurai un peu élagué ce code mal gaulé et assez confu. J'ai encore du mal à en avoir une vision macro permettant de redéfinir une archi "éclairée".

  8. #8
    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
    Un truc a base de variadic template, ca peut pas le faire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <iostream>
     
    using namespace std;
     
    struct poly
    {
      template <class ...Args> void foo(Args... a)
        {
          resize(a...);
        }
    private :
      virtual void resize(int,int)=0;
      virtual void resize(int i)=0;  
    };
     
    struct Carre : poly
    {
    private :
      virtual void resize(int,int){}
      virtual void resize(int i){std::cout<<"Carre int"<<std::endl;}  
    };
    struct Rect : poly
    {
    private :
      virtual void resize(int,int){std::cout<<"Rect 2"<<std::endl;}
      virtual void resize(int i){}  
    };
     
     
    int main()
    {
      Carre b;
      poly* a=&b;  
      a->foo(4);
      a->foo(4,5);
      Rect c;
      a=&c;
      a->foo(4,2);
    }
    le soucis avec cette methode, c'est que tu as la moitie des fonctions qui ne servent a rien et ca fait du code mort.

    P-e qu'avec du CRTP ya moyen de diminuer ca.
    "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)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 637
    Par défaut
    Citation Envoyé par oodini Voir le message
    C'est là qu'est l'os, hélas.

    Pour le début de ton intervention, nous sommes biens d'accord.

    Pour la suite, le problème est que le code concerné est sensible aux performances. En fait, une partie des arguments serait regroupable par paires (les structures de données existent déjà). Je pourrais me retrouver avec 5 arguments plutôt que 8. Mais construire les objets prendrait du temps sans que cela ait un apport fonctionnel.
    Je n'ai pas dit qu'il fallait utiliser cette technique partout

    J'ai dit que, de manière exceptionnelle, le fait d'avoir une telle structure permettait de rendre ta liste de paramètres plus cohérente

    Et surtout, si tu es sensisble aux performances, j'ai envie de dire qu'il y a, de toutes manières bien des possibilités à explorer au niveau de l'algorithme, avant de t'inquiéter d'une indirection supplémentaire

    L'idée ici est d'utiliser l'héritage plus comme un moyen d’agréger des données que comme un moyen de profiter du polymorphisme

    Ceci dit, si les valeurs sont toutes de même type, rien ne t'empêche de carrément passer un std::vector par référence, même si on en revient au problème de base : la difficulté de savoir à quoi correspond la quatrième valeur
    Alors utiliser ajouter une indirection et utiliser du dynamic_cast...
    Un static_cast ou un cast C style pourrait parfaitement suffire également

    Le problème, c'est que cela laisse plus facilement le développeur faire des bêtises (et risquer de passer la structure à 3 arguments quand il faut la structure à 5 )
    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
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par oodini Voir le message
    Pour simplifier à l'extrême
    Un peu trop, je comprends pas comment ce qui suit est possible:

    de manière polymorphique, je veux appeler une méthode Redimensionner(). Selon la classe sous-jacente, le nombre d'arguments nécessaire ne sera pas le même.
    Ou tu fais un appel polymorphe et tu es incapable de passer un nombre d'arguments qui dépend de la classe la plus dérivée, ou tu ne fais pas un appel polymorphe. Dans les deux cas, je ne vois pas quel est le problème.

  11. #11
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Citation Envoyé par oodini Voir le message
    C'est là qu'est l'os, hélas.

    Pour le début de ton intervention, nous sommes biens d'accord.

    Pour la suite, le problème est que le code concerné est sensible aux performances. En fait, une partie des arguments serait regroupable par paires (les structures de données existent déjà). Je pourrais me retrouver avec 5 arguments plutôt que 8. Mais construire les objets prendrait du temps sans que cela ait un apport fonctionnel.

    Alors utiliser ajouter une indirection et utiliser du dynamic_cast...

    Je crois que je me repencherai dessus plus tard quand j'aurai un peu élagué ce code mal gaulé et assez confu. J'ai encore du mal à en avoir une vision macro permettant de redéfinir une archi "éclairée".
    sans préjuger de tes contraintes, tu es sûr de ne pas pouvoir redéfinir la notion de redimensionnement de façon uniforme (facteur d'échelle, ou cefX + coefY [+ coef Z])? Sinon où est le polymorphisme là dedans? Si tu appelles de manière ensembliste sur un container, tu as bien un paramètre global, mais si tu appelles forme par forme pour définir le redimensionnement, alors WFT le container et le polymorphisme?

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Ou tu fais un appel polymorphe et tu es incapable de passer un nombre d'arguments qui dépend de la classe la plus dérivée, ou tu ne fais pas un appel polymorphe. Dans les deux cas, je ne vois pas quel est le problème.
    Exactement. Et je cherchais donc un moyen de me débarrasser de cet appel polymorphe en ayant recours à un quelconque design pattern que vous auriez pu connaître pour résoudre ce problème.

  13. #13
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Mais comment diantre cet appel polymorphe à tiroir et à piston est-il actuellement fait?
    Si les paramètres doivent être redéfinis pour chaque forme quel est l'attendu global?

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    L'attendu global, c'est le calcul d'un coût. Son calcul dépend d'un nombre variable d'arguments selon l'objet sur lequel se fait le calcul. Et la valeur de ces arguments n'est pas connue au moment de la construction des instance et leur insertion dans le conteneur.

    Exemple débile :

    Disons que tu tiens une sandwicherie. Tu veux mettre à jour le prix de ta carte toutes les demi-heures en fonctions du prix des ingrédients côtés en bourse. Chaque type de sandwich pourrait avoir une fonction updatePrice().
    Dès que tu reçois l'ensemble des prix de tes ingrédients, tu parcours l'ensemble des sandwiches de ta carte (le conteneur), et tu appelles updatePrice().
    Sauf qu'il y a des sandwiches jambon-beurre, jambon-emmental, jambon_cru-reblochon, tomates-mozarelle, etc...
    Tu peux appeler séquentiellement les updatePrice() avec leur liste de prix spécifique, mais on se retrouve alors dans le problème de maintenance évoqué par koala01 avec ses dynamic_cast.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 637
    Par défaut
    Cet exemple n'a strictement rien de commun avec l'exemple que tu présentais avant!

    Ici, il n'y a strictement rien qui t'empêche d'avoir la liste des différents prix, ni aux sandwiches de savoir exactement de quel ingrédients ils ont besoin, et en quelle quantité.

    Si donc tu as la liste des prix (en € au kilo) pour les matières premières PriceList, qui permet de récupérer le prix de chaque élément utilisé (jambon, parme, mayonnaise, beurre, fromage, ...), tu peux parfaitement transmettre simplement cette liste à ta fonction updatePrice.

    A partir de là, chaque sandwich peut adapter son comportement sous une forme qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void JambonBeurre::updatePrice(PriceList const & pl){
        double jambon = pl.jambon() / 1000 * quantite * marge;
        double beurre =  pl.beurre() / 1000 * quantite * marge;
        double pain = pl.painBlanc() / 1000 * quantite * marge;
        price_ = (jambon + beurre + pain) * tva;
    }
    Et, comme tu auras sans doute aussi utilisé un tout petit peu le patron de conception "décorateur" (parce qu'un jambon beurre peut être agrémenté de quelques trucs), cela pourrait tout aussi prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void JambonBeurre::updatePrice(PriceList const & pl){
        jambon.computePrice(pl); // la part de jambon calcule son prix
                                 // (en fonction de la quantité dont elle a besoin)
        beurre.computePrice(pl); // idem pour le beurre
        pain.computePrice(pl); // idem pour le pain
        /*... */
        price_ = computeTotal(); // calcule le total de toutes les parts
    }
    Au final, on n'a plus qu'un et un seul argument (une structure, soit, mais un seul argument quand même), dont chaque classe dérivée va chercher "la valeur" qui l'intéresse et la manipule en fonction des besoins qui lui sont propres

    Tu peux donc sans aucun problème utiliser le polymorphisme et envisager de faire un traitement global sur tous tes objets, basé sur une liste de prix clairement définie
    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

  16. #16
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par oodini Voir le message
    Exemple débile :

    Disons que tu tiens une sandwicherie. Tu veux mettre à jour le prix de ta carte toutes les demi-heures en fonctions du prix des ingrédients côtés en bourse. Chaque type de sandwich pourrait avoir une fonction updatePrice().
    Dès que tu reçois l'ensemble des prix de tes ingrédients, tu parcours l'ensemble des sandwiches de ta carte (le conteneur), et tu appelles updatePrice().
    1/ De toute manière, je n'hardcode pas les ingrédients dans ce genre de conception
    2/ Tes sandwitch sont des observeurs du prix de chacun des ingrédients et ils sont notifiés des modifications, t'a pas à parcourir une liste de tous les sandwitchs.
    3/ Je ne vois toujours pas quel est le problème à résoudre même avec une autre conception. Ou tu filtres ta liste en fonction des prix modifiés, ou tu laisses les objets ignorer les notifications pour les matières qui ne les intéressent pas ou tes objets se recalculent de toute manière systématiquement -- pour le nombre de sandwitchs sur une carte, ça ne vaut pas la peine de mettre en place quelque chose de plus complexe.

Discussions similaires

  1. [Débutant] évaluation d'une fonction avec de variable symbolique
    Par rafrouf2010 dans le forum MATLAB
    Réponses: 3
    Dernier message: 13/11/2012, 21h06
  2. Réponses: 5
    Dernier message: 11/08/2011, 14h12
  3. Appel d'une fonction avec plusieurs variables
    Par midoparis dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 13/05/2008, 11h53
  4. Créer une fonction avec une variable
    Par Ricou13 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 22/01/2007, 23h51
  5. Fonction avec parametre variable
    Par Linaa dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 17/12/2006, 12h41

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