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 :

Classe options et polymorphisme


Sujet :

C++

  1. #1
    Invité
    Invité(e)
    Par défaut Classe options et polymorphisme
    Bonsoir,

    J'avais lu il y a quelques temps sur Dr Dobbs un article assez interressant sur les classes options. Ce qui m'interesse est l'un des premiers exemples :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    File f = OpenFile( "foo.txt" )
       .readonly()
       .createIfNotExist()
       .appendWhenWriting()
       .blockSize( 1024 )
       .unbuffered()
       .exclusiveAccess();
    J'ai trouvé l'idée de **cacher** la la classe d'options très... hum ... esthétique.
    Par ailleurs, j'ai voulu essayer de creer un petites classe de generalisation de GUI( prenons par exemple qt et wxWidget). Pour permettre à chaque GUI d'obtenir les information qui lui vont bien j'ai pensé aux classe d'options :
    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 GenericGui
    {
     
    };
     
    class QtImpl : public GenericGui
    {
    public:
         class Option
         {
     
         };
    };
     
    QtImpl::Option useQtGui();
     
    class wxWidgetImpl : public GenricGui
    {
    public:
         class Option
         {
     
         };
    };
     
    wxWidgetImpl::Option usewxWidgetGui();
    L'idée est de pouvoir les utiliser comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GenericGui* gui(useQtGui().option1(true).option2(2.5));
    Je vois en gros deux solution mais la premiere me parait crade et la seoncde me gène un peu :
    • ou je crée un operateur de conversion dans mes classes options vers GenericGui*
    • ou je crée une fonction membre(ou un operateur) qui renvoie un GenericGui*


    En gros j'aimerais connaitre votre avis.

    Merci d'avance

  2. #2
    En attente de confirmation mail

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

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Je ne comprend pas trop ce que tu cherches à faire, l'idiom des paramètre nommé, en gros c'est ca :
    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
    class Option
    {
      public:
        Option& param(bool b) { p = b; return *this; }
      private:
        friend class Final;
        bool p;
    };
     
    class Final
    {
      public:
        Final(const Option& opt) : param(opt.p) {}
      private:
        bool param;
    };
    Je ne vois pas ce que vient faire ici le fait d'utiliser Qt ou wx en API de base, ceci devrait plûtot être réglé par une politique pour la classe Final, en ajoutant un classe de base commune par dessus si tu veux manipuler à la fois les deux (cf type erasure).

    L'utilisation de Qt ou wx ne devrait pas influencer la facon dont ton système décide de représenter les attributs des tes widgets, c'est contraire au DIP.

    Ensuite tu peux décider de faire une classe spécifique OptionQt qui ressemble aux options de Qt et qui possède un opértateur de conversion vers Option (implicite ou explicite, mais ici implicite me semble mieux).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class OptionQt
    {
      public:
        OptionQt& param(bool b) { p = b; return *this; }
        operator Option() { return Option().param(p); }
      private:
        bool p;
    };

  3. #3
    Invité
    Invité(e)
    Par défaut
    Ce que je cherche à faire, c'est mixer les parametres nommés avec une sorte de pattern factory. Le resultat serait d'obtenir une utilisation ressemblant à celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void fonction( GenericGui* gui);
     
    int main()
    {
    // utilise Qt
          fonction( useQt().setStyleSheet(" style sheet ")  // des options spécifiques à Qt
                                  .setApplicationName("App")
                                  .setVersion("5.3.2") );
     
    // maintenant utilise wxWidget
         fonction( usewxWidget().setExitOnFrameDelete(true) ) // des options spécifiques à wxWidget
    }
    L'utilisateur ne doit donc ni connaitre l'existence de QtImpl ou wxWidgetImpl, ni celle des classes de configuration.

  4. #4
    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
    Oui, ce que j'ai fait permet de faire ca, en adaptant un peu :
    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
    #include<cstdlib>
    #include<cstddef>
     
    //Debut Code de Base
    class Option
    {
      public:
        Option& param(bool b) { p = b; return *this; }
      private:
        friend class GenericGui;
        bool p;
    };
     
    class GenericGui
    {
      public:
        GenericGui(const Option& opt) : param(opt.p) {}
      private:
        bool param;
    };
    //Fin Code de Base
     
    //Une classe de configuration pour Qt
    class OptionQt
    {
      public:
        OptionQt& param_qt(bool b) { p = b; return *this; }
        //Operateur de conversion implicite vers la classe d'option classique
        operator Option() { return Option().param(p); }
      private:
        bool p;
    };
     
    //Une fonction, utiliser une rref pour si tu veux te passer du const
    void fonction(GenericGui&&) {}
     
    int main()
    {
      //Utilisation
      fonction(GenericGui(OptionQt().param_qt(true)));
      system("PAUSE");
      return EXIT_SUCCESS;
    }
    Avec ceci, l'utilisateur n'a pas besoin de plus de connaisance que dans ton code, on utilise juste une OptionQt à la place de useQt, mais sinon ca revient au même. Evidament, ici la correspondance entre les paramètres spcifique Qt (param_qt) et generique (param) est trivial, mais on peut imaginer n'importe quoi de plus complexe.

  5. #5
    Invité
    Invité(e)
    Par défaut
    En fait la classe GenericGui presente des fonctions virutelle pure(voila le lien avec le polymorphysme) : qui permettent d'utiliser de facon générique les bibliothèques de gui. Par exemple un fonction pour detruire toutes le fenetre, une fonction pour toutes les dessiner, et ainsi de suite... Le role des classes d'options pourrait donc etre double : elles recupèrent les parametre de la classe à laquelle elles sont liées, puis construisent une instance de cette classe et renvoient un pointeur vers cette instance( éventuellement un pointeur vers la classe de base, GenericGui)

  6. #6
    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
    Commencer à multpilier les rôles d'une classe c'est se retrouver à l'encontre du SRP ou pire, avoir une God-Class.

    Pour faire ce que tu veux tu peux faire comme j'ai dit dans mon premier message : compler classes de Politique, type Erasure, NPI.

    Par exemple :
    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
    #include<cstdlib>
    #include<cstddef>
     
    #include<iostream>
     
    //Debut Code de Base
    class Option
    {
      public:
        Option& param(bool b) { p = b; return *this; }
      private:
        friend class AbstractGui;
        bool p;
    };
     
    class AbstractGui
    {
      public:
        AbstractGui(const Option& opt) : param(opt.p) {}
        virtual ~AbstractGui(){}
        virtual void method() =0;
      private:
        bool param;
    };
     
    template<class Policy>
    class ConcretGui : public AbstractGui, public Policy
    {
      public:
        template<class O>
        ConcretGui(const O& opt) : AbstractGui(opt), Policy(opt) {}
        void method() {Policy::method();}
    };
    //Fin Code de Base
     
    //Code pour Qt
    class OptionQt
    {
      public:
        OptionQt& param_qt(bool b) { p = b; return *this; }
        //Operateur de conversion implicite vers la classe d'option classique
        operator Option() const { return Option().param(p); }
      private:
        friend class QtPolicy;
        bool p;
    };
     
    class QtPolicy
    {
      public:
        QtPolicy(const OptionQt& opt) : param_qt(opt.p) {}
        void method() {std::cout << param_qt;}
      protected:
        ~QtPolicy() {}
      private:
        bool param_qt;
    };
    //Fin de Code pour Qt
     
    int main()
    {
      AbstractGui* p = new ConcretGui<QtPolicy>(OptionQt().param_qt(true));
      p->method();
      delete p;
      system("PAUSE");
      return EXIT_SUCCESS;
    }
    C'est juste un enchainement des 3 techniques, avec un changement qui permet de faire le lien, il s'agit du constructeur template, il permet de ne pas transtyper tout de suite le type de la classe d'option et donc de pouvoir jouer avec l'amitié sur deux tableau : entre OptionQt et QtPolicy puis entre Option et AbstractGui.

    Si ce n'est toujours pas ca, alors je ne comprend pas trop ce que tu veux faire :s

  7. #7
    Invité
    Invité(e)
    Par défaut
    Non, non, ce que je veux faire est beaucoup plus simple, ce que tu me présente va bien au de-là. Ma seule question concerne cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    AbstractGui* p = new ConcretGui<QtPolicy>(OptionQt().param_qt(true));
    J'aurais voulu que l'utilisateur n'ai pas connaissance de ConcretGui. Mais maintenant que tu me le présente comme cela, il suffit de typedefer la politique dans la classe d'options et passer par une fonction créatrice :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<class Opt>
    AbstractGui* use(Opt const& opt)
    {
          return new ConcreteGui<Opt::Policy>(opt);
    }
    Merci pour tes réponses
    Dernière modification par Invité ; 12/12/2010 à 17h54.

  8. #8
    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
    D'accord, je voyais pas ta question comme ca, en effet la méthode que tu utilises marche bien, mais bon ca permet juste de simplifier un tout petit peu, à la place de préciser deux fois qu'il s'agit de Qt (ConcretGui<QtPolicy> et QtOption), on ne le précise qu'une seul fois.

    Au passage, le lien que tu cites au début (que j'avais pas lu), ne fait pas que présenter le NPI, il en montre un défaut et des technique pour les résoudre qui sont plus complexe qu'un simple NPI, pour une préentation simple il y a une entrée dans la FaQ Lite.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/01/2010, 12h21
  2. Option de classe dans un .cls
    Par Gébix dans le forum Distributions
    Réponses: 4
    Dernier message: 15/01/2007, 10h58
  3. [C#] Classe C# et attribut Browsable fonction d'une option
    Par ILoveCSharp dans le forum Windows Forms
    Réponses: 3
    Dernier message: 03/06/2006, 02h13
  4. DHCP client, option Vendor class identifier
    Par Annaced dans le forum Protocoles
    Réponses: 1
    Dernier message: 20/04/2006, 21h58
  5. polymorphisme, pointeurs et classes abstraites
    Par legend666 dans le forum C++
    Réponses: 10
    Dernier message: 02/11/2005, 17h44

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