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 :

interfaces et états


Sujet :

C++

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

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

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

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

    c'est un problème de conception, mais la solution va certainement être très spécifique au c++, c'est pourquoi je poste ici.

    Je travaille sur une application qui, basiquement, affiche des images à l'écran. Ces images ont diverses propriétés. Par exemple elles peuvent bouger, et/ou être cliquées, et/ou être sélectionnées, etc.

    J'ai donc décidé d'opter pour une programmation par contrat: j'implémente des interfaces (Movable, Clickable, Selectionnable, etc.) et mes images (Sprites) héritent des ces interfaces en fonctions des besoins.

    Jusqu'ici tout va bien, et ça marche plutôt pas mal (je veux dire d'un point de vue de l'architecture: tout s'emboite bien, et les modifications/ajouts de fonctionnalités se passent bien).

    Mais maintenant, je voudrais que mes images puissent changer de comportement. Par exemple, immobiliser une image qui était "movable". Il faudrait donc que je lui enlève l'interface Movable. Or ce n'est évidemment pas possible.

    Donc en fait, le problème c'est que j'ai des objets qui sont suscpetibles de changer d'état finalement. Ce qui pourrait m'orienter vers l'utilisation du dp state. Mais l'utilisation de ces interfaces est vraiment hyper pratique, propre, et assez élegant je trouve. Et puis là je vous en donne 3, mais en vrai il y en a plus. Je ne voudrais donc pas laisser tomber ces interfaces. Mais alors comment faire pour que mes objets puissent changer d'état?

    J'aimerais également éviter de reconstruire mes objets lorsqu'ils changent d'état, car j'utilise un gestionnaire de mémoire pour les images très optimisé mais très peu pratique.
    J'ai l'intuition que je vais avoir besoin de templates...

    J'espère avoir été clair. Si ça ne l'est pas, dites-le moi je posterai un diagramme, c'est toujours plus parlant.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  2. #2
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Là comme ça, ça me fait plutôt penser au design pattern décorateur.

    MAT.

  3. #3
    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
    Si je comprends bien tu as quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class InterfaceA
    {
      virtual void fooA() =0;
      protected:
        virtual InterfaceA(){}
    }
    //Idem pour B, C, D, ... plein
    class SpriteA : public InterfaceA
    {Data d; public: void fooA(){/*Code utilisant d*/} };
    class SpriteAB : public InterfaceA, public Interface B
    { /*code*/ };
    /*idem plein d'autre*/
    //Avec une classe de base commune peut-etre ?
    Et tu voudrais faire un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SpriteAB s;
    s.remove<InterfaceA>();
    Si c'est ca me semble difficile "sans rien créer" d'autre, car l'interface est lié au type statique, et tu ne peux pas le changer sans rien créer.

    Tu pourrais passer par un système qui isole l'implémentation de ta classe de son interface (comme PImpl), ca permettrait au système qui gère la mémoire de ne s'occuper que de ces derniers, et dans la couche supérieur tu pourrais switcher entre les interfaces en créant de nouveau objet.

    Quelque chose comme ca (j'ai fait ajouter une interface). pour en retirer une, avec ce code il faut déterminer la listes des types voulue (enlever l'interface qu'il faut, boost doit proposer ca), et après c'est pareil que pour add.

    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
     
    struct SpriteImpl
    { /*data*/ };
     
    class BaseSprite
    { 
      BaseSprite(const BaseSprite&) =delete;
      template<class,class...> friend class ManageInterface;
      protected:
        SpriteImpl* p;
        void take(BaseSprite& s) { std::swap(p,s.p); delete s.p; s.p = NULL; }
      public:
        BaseSprite() : p(new SpriteImpl()) {}
        virtual ~BaseSprite(){ delete p; }
    };
     
    template<class...> class Sprite : public BaseSprite {};
     
    template<class Interface, class... Arg>
    class ManageInterface
    { protected: ~ManageInterface(){}
      public:
        template<class T>
        std::unique_ptr<Sprite<T,Interface,Arg...> > add()
        { Sprite<T,Interface,Arg...>* s = new Sprite<T,Interface,Arg...>(); 
          s->take(*(reinterpret_cast<BaseSprite*>(this)));
          return std::unique_ptr<Sprite<T,Interface,Arg...> >(s); }
    };
     
    class InterfaceA;
    template<class... Arg>
    class Sprite<InterfaceA,Arg...> :
      public Sprite<Arg...>, public ManageInterface<InterfaceA,Arg...>
    { public: virtual void fooA(){/*impl*/} };
     
    class InterfaceB;
    template<class... Arg>
    class Sprite<InterfaceB,Arg...> :
      public Sprite<Arg...>, public ManageInterface<InterfaceB,Arg...>
    { public: virtual void fooB(){/*impl*/} };
     
    //Exemple d'utilisation
    Sprite<InterfaceA> s;
    s.fooA();
    auto s2 = s.add<InterfaceB>();
    s2->fooB();
    Si c'est pas du tout l'objectif que tu as, alors je n'ai pas compris la question.

    <Edit> Et on peut faire une macro sur le code pour éviter la répétition quand on définie de nouvelles interfaces :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #define Interface(E) \
    class Interface##E; \
    template<class... Arg> \
    class Sprite<Interface##E,Arg...> : \
      public Sprite<Arg...>, public ManageInterface<Interface##E,Arg...> \
     
    //Génère le code concernant InterfaceA dans le début du code
    Interface(A)
    { public: virtual void fooA(){/*impl*/} };
    </Edit>

  4. #4
    screetch
    Invité(e)
    Par défaut
    hmmm dans ce cas je n'aime pas trop l'héritage. De la composition serait peut être plus efficace.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Region
    {
      Movable* onMove;
      Clickable* onClick;
      Selectionnable* onSelected;
    };
    ainsi il suffit de remplacer le onMove pour changer le comportement de déplacement, sans changer le comportement de clickable ou selectionnable.

  5. #5
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par screetch Voir le message
    hmmm dans ce cas je n'aime pas trop l'héritage. De la composition serait peut être plus efficace.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Region
    {
      Movable* onMove;
      Clickable* onClick;
      Selectionnable* onSelected;
    };
    ainsi il suffit de remplacer le onMove pour changer le comportement de déplacement, sans changer le comportement de clickable ou selectionnable.
    +1 pour la composition. (mais pourquoi des pointeurs?)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  6. #6
    screetch
    Invité(e)
    Par défaut
    bah pour le polymorphisme? j'ai dit une betise?

  7. #7
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Non non, mon message était incomplet à vrai dire. (je voulais dire pourquoi des pointeurs nus).
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  8. #8
    screetch
    Invité(e)
    Par défaut
    ah ben ca c'est sur que c'est une mauvaise idée mais je fais confiance a r0d la dessus

  9. #9
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Moi aussi, c'est juste la force de l'habitude. (non je suis pas un bot promis).
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  10. #10
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Septembre 2006
    Messages : 37
    Points : 64
    Points
    64
    Par défaut
    Je n'ai pas regardé la solution de Florian dans le détail.

    J'ai écrit une première solution :

    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
    #include <iostream>
     
     
    struct BaseInterface { virtual ~BaseInterface()= 0; };
     
    inline
    BaseInterface::~BaseInterface()= default;
     
     
    // Tags
    struct A; struct B; struct C;
     
     
    template< typename... Tags >
    struct Interface;
     
    template<>
    template< typename Car, typename... Cdr >
    struct Interface< Car, Cdr... >:
     virtual public BaseInterface,
     virtual public Interface< Car >,
     virtual public Interface< Cdr... > {
     
    };
     
     
    // Interfaces
    template<>
    struct Interface< A >:
     virtual public BaseInterface {
     
      virtual void a()= 0;
    };
     
    template<>
    struct Interface< B >:
     virtual public BaseInterface {
     
      virtual void b()= 0;
    };
     
    template<>
    struct Interface< C >:
     virtual public BaseInterface {
     
      virtual void c()= 0;
    };
     
     
     
     
    template< typename _Who, typename... What >
    struct Implementation;
     
    template< typename _Who, typename _Car, typename... Cdr >
    struct Implementation< _Who, Interface< _Car, Cdr... > >:
     virtual public Implementation< _Who, Interface< _Car > >,
     virtual public Implementation< _Who, Interface< Cdr... > > {
     
    };
     
     
    template< typename... Args >
    struct Sprite;
     
    // Implementation
    template<>
    struct Implementation< Sprite< A, B, C >, Interface< A > >:
     virtual public Interface< A > {
     
     void a() /* override */ {
     
       std::cout << "Implementation of a() for Sprite< A, B, C >\n";
     }
     
    };
     
    template<>
    struct Implementation< Sprite< A, B, C >, Interface< B > >:
     virtual public Interface< B > {
     
     void b() /* override */ {
     
       std::cout << "Implementation of b() for Sprite< A, B, C >\n";
     }
     
    };
     
    template<>
    struct Implementation< Sprite< A, B, C >, Interface< C > >:
     virtual public Interface< C > {
     
     void c() /* override */ {
     
       std::cout << "Implementation of c() for Sprite< A, B, C >\n";
     }
     
    };
     
     
    template<>
    struct Sprite< A, B, C >:
     virtual public Implementation< Sprite< A, B, C >, Interface< A, B, C > >  {
     
    };
     
     
    template< typename _Sprite, typename... Args >
    struct State;
     
    template<>
    template< typename _Sprite, typename _Car, typename... Cdr >
    struct State< _Sprite, _Car, Cdr... >:
     virtual public Implementation< _Sprite, Interface< _Car > >,
     virtual public Implementation< _Sprite, Interface< Cdr... > > {
     
    };
     
    template<>
    template< typename _Sprite, typename _Tag >
    struct State< _Sprite, _Tag >:
     virtual public Implementation< _Sprite, Interface< _Tag > > {
     
    };
     
     
     
    template< typename... Args >
    inline State< Sprite< Args... >, Args... > &
    step(
      Sprite< Args... > & sprite) {
     
      return reinterpret_cast< State< Sprite< Args... >, Args... > & >(sprite);
    }
     
    inline State< Sprite< A, B, C >, A, B > &
    step(
      State< Sprite< A, B, C >, A, B, C > & state) {
     
      return reinterpret_cast< State< Sprite< A, B, C >, A, B > & >(state);
    }
     
    inline State< Sprite< A, B, C >, A, B, C > &
    step(
      State< Sprite< A, B, C >, A, B > & state) {
     
      return reinterpret_cast< State< Sprite< A, B, C >, A, B, C > & >(state);
    }
     
     
    int
    main() {
     
      Sprite< A, B, C > sprite;
      State< Sprite< A, B, C >, A, B, C > & state0(step(sprite));
      std::cout << "State 0:\n";
      state0.a();
      state0.b();
      state0.c();
     
      State< Sprite< A, B, C >, A, B > & state1(step(state0));
      std::cout << "State 1:\n";
      state1.a();
      state1.b();
      state1.c(); compile time error
     
      State< Sprite< A, B, C >, A, B, C > & state2(step(state1));
      std::cout << "State 2:\n";
      state2.a();
      state2.b();
      state2.c();
    }
    Mais les reinterpret_cast la rende fragile. Aussi j'ai confié la gestion de la référence au sprite aux états.

    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
    #include <iostream>
     
     
    struct BaseInterface { virtual ~BaseInterface()= 0; };
     
    inline
    BaseInterface::~BaseInterface()= default;
     
     
    // Tags
    struct A; struct B; struct C;
     
     
    template< typename... Tags >
    struct Interface;
     
    template<>
    template< typename Car, typename... Cdr >
    struct Interface< Car, Cdr... >:
     virtual public BaseInterface,
     virtual public Interface< Car >,
     virtual public Interface< Cdr... > {
     
    };
     
     
    // Interfaces
    template<>
    struct Interface< A >:
     virtual public BaseInterface {
     
      virtual void a()= 0;
    };
     
    template<>
    struct Interface< B >:
     virtual public BaseInterface {
     
      virtual void b()= 0;
    };
     
    template<>
    struct Interface< C >:
     virtual public BaseInterface {
     
      virtual void c()= 0;
    };
     
     
     
     
    template< typename _Who, typename... What >
    struct Implementation;
     
    template< typename _Who, typename _Car, typename... Cdr >
    struct Implementation< _Who, Interface< _Car, Cdr... > >:
     virtual public Implementation< _Who, Interface< _Car > >,
     virtual public Implementation< _Who, Interface< Cdr... > > {
     
    };
     
     
    template< typename... Args >
    struct Sprite;
     
    // Implementation
    template<>
    struct Implementation< Sprite< A, B, C >, Interface< A > >:
     virtual public Interface< A > {
     
     void a() /* override */ {
     
       std::cout << "Implementation of a() for Sprite< A, B, C >\n";
     }
     
    };
     
    template<>
    struct Implementation< Sprite< A, B, C >, Interface< B > >:
     virtual public Interface< B > {
     
     void b() /* override */ {
     
       std::cout << "Implementation of b() for Sprite< A, B, C >\n";
     }
     
    };
     
    template<>
    struct Implementation< Sprite< A, B, C >, Interface< C > >:
     virtual public Interface< C > {
     
     void c() /* override */ {
     
       std::cout << "Implementation of c() for Sprite< A, B, C >\n";
     }
     
    };
     
     
    template<>
    struct Sprite< A, B, C >:
     virtual public Implementation< Sprite< A, B, C >, Interface< A, B, C > >  {
     
    };
     
     
     
    template< typename _Sprite >
    struct BaseState {
     
     _Sprite & sprite_;
     
     BaseState(
       _Sprite & sprite):
       sprite_(sprite) {
     }
     
    };
     
     
    template< typename _Sprite, typename... Args >
    struct State;
     
    template<>
    template< typename _Sprite, typename _Car, typename... Cdr >
    struct State< _Sprite, _Car, Cdr... >:
     virtual public BaseState< _Sprite >,
     virtual public Implementation< _Sprite, Interface< _Car > >,
     public State< _Sprite, Cdr... > {
     
     State(
       _Sprite & sprite):
       BaseState< _Sprite >(sprite),
       Implementation< _Sprite, Interface< _Car > >(),
       State< _Sprite, Cdr... >(sprite) {
     
     }
     
     
     operator Implementation< _Sprite, Interface< _Car > > &() {
     
       return this->sprite_;
     }
     
    };
     
    template<>
    template< typename _Sprite, typename _Tag >
    struct State< _Sprite, _Tag >:
     virtual public BaseState< _Sprite >,
     virtual public Implementation< _Sprite, Interface< _Tag > > {
     
     State(
       _Sprite & sprite):
       BaseState< _Sprite >(sprite),
       Implementation< _Sprite, Interface< _Tag > >() {
     
     }
     
     operator Implementation< _Sprite, Interface< _Tag > > &() {
     
       return this->sprite_;
     }
     
    };
     
     
     
    template< typename... Args >
    inline State< Sprite< Args... >, Args... > 
    step(
      Sprite< Args... > & sprite) {
     
      return State< Sprite< Args... >, Args... >(sprite);
    }
     
    inline State< Sprite< A, B, C >, A, B > 
    step(
      State< Sprite< A, B, C >, A, B, C > state) {
     
      return State< Sprite< A, B, C >, A, B >(state.sprite_);
    }
     
    inline State< Sprite< A, B, C >, A, B, C > 
    step(
      State< Sprite< A, B, C >, A, B > state) {
     
      return State< Sprite< A, B, C >, A, B, C >(state.sprite_);
    }
     
     
    int
    main() {
     
      Sprite< A, B, C > sprite;
      State< Sprite< A, B, C >, A, B, C > state0(sprite);
      std::cout << "State 0:\n";
      state0.a();
      state0.b();
      state0.c();
     
      State< Sprite< A, B, C >, A, B > state1(step(state0));
      std::cout << "State 1:\n";
      state1.a();
      state1.b();
      // state1.c(); // compile time error
     
      State< Sprite< A, B, C >, A, B, C > state2(step(state1));
      std::cout << "State 2:\n";
      state2.a();
      state2.b();
      state2.c();
    }
    Mais je n'ai peut-être rien compris à ton problème...

  11. #11
    Invité
    Invité(e)
    Par défaut
    Salut,

    Citation Envoyé par r0d Voir le message
    Mais maintenant, je voudrais que mes images puissent changer de comportement. Par exemple, immobiliser une image qui était "movable". Il faudrait donc que je lui enlève l'interface Movable. Or ce n'est évidemment pas possible.
    La solution va dépendre de ce que tu entends par "changer".

    Si ce que tu veux, c'est "juste" que certains les comportements puissent être inhibés, alors le plus simple est d'ajouter une propriété "Enabled" à tes interfaces. Celle ci sera vérifiée à chaque fois qu'on utilise l'interface. En gros, un objet cliquable est toujours cliquable (potentiellement) mais sa "cliquabilité" peut être désactivée via la propriété Enabled...

    Ca a le mérite d'être très simple, quoiqu'un peu intrusif si tu l'implémentes dans du code existant (encore que... si tu pars du principe que tes interfaces sont actives par défaut...).

    Si tu veux que la même interface puisse changer de comportement, alors tu es davantage dans l'approche "gestionnaire d'évènements" que suggérait Screetch. En gros, tes interfaces communiquent avec ton objet au travers de foncteurs, que tu peux "débrancher", un "cliquable désactivé", c'est alors un objet dont le "foncteur de clic" est débranché. Cette seconde approche est plus puissante (elle va te permettre de modifier les comportements de tes interfaces à l'éxécution), mais également plus lourde à mettre en oeuvre.

    Ce genre de situation est très courant dans les librairies d'interface. La difficulté,c'est que tes comportements (ie les fonctions membres de ton interface) vont devoir faire référence à l'instance qui les appelle (et donc connaitre son type, ses membres...). C'est un peu plus compliqué qu'un pointeur de fonction.

    Traditionnellement, c'était géré en utilisant des hiérarchies dérivant d'objets communs (c'est comme cela que font la VCL de Borland, et Qt, en partie). Le 'super objet' avait pour seule fonction de permettre cette "communication ascendante' entre le gestionnaire d'évènement et son appelant.

    Aujourd'hui, on recommanderait de faire sans "super Objet". C'est faisable, mais pas aussi simple que ca en a l'air. Si tu te lances là dedans, regarde le chapitre "smart pointers" de Modern C++ Design (Alexandrescu)... Ca permet de bien comprendre la problématique (même si après tu utilises une solution préfabriquée).

    Francois
    Dernière modification par Invité ; 19/02/2011 à 17h55.

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

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

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

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

    pardon de n'avoir pas répondu avant, j'étais en déplacement ces jours-ci.
    Je vais regarder tout ça puis je vous tiens au courant.
    Merci pour vos réponses
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

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

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

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Ok alors après réflexion, je pense que le plus simple et le moins compliqué ce sera un décorateur. Ce qui, finalement, reviens à la proposition de screetch. Je vais donc partir là-dessus, on verra si je rencontre des difficultés insurmontables

    Au passage, dans cette situation moi je n'ai aucun scrupule à utiliser des pointeurs nus. En effet, ces pointeurs ne seront pas exportés en dehors de la classe, et je pense même pouvoir les gérer dans une classe "super object" commune à tous les types de sprite.

    Enfin, peux-être dis-je des bêtises et les problèmes apparaîtrons lors de l'implémentation. On verra
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

Discussions similaires

  1. gestion des aute élément d'interface suivant l'état d'un expander
    Par boubou38 dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 26/07/2012, 10h50
  2. Réponses: 1
    Dernier message: 26/01/2009, 14h33
  3. Réponses: 12
    Dernier message: 23/11/2005, 11h06
  4. Réponses: 36
    Dernier message: 28/09/2005, 12h30
  5. Réponses: 5
    Dernier message: 08/07/2002, 16h22

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