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 :

Créer une liste d'objets de template


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut Créer une liste d'objets de template
    Bonsoir à tous!
    Suite de mes threads précédent, j'essaye de factoriser du code en créant des templates.

    Je me heurte à un problème:
    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
     
    //Ma classe d'option permettant de stocker une information
    template<typename T>
    class Option
    {
    private:
      T value_;
    public:
      Option(const T& value) : value_(value) {};
      virtual ~Option(){};
      const T& operator()() const { return value_;};
    };
     
    class AbstractOptions
    {
    public:
      //Ajoute les options des classes concretes  une liste passée en paramètre.
      virtual void addOptions(std::vector<Option<???> >& optionList) = 0; //Comment faire pour passer un type inconnu??
    };
     
    class ConcreteOptions
    {
    private:
      Option<double> option1_;
      Option<int> option2_;
    public:
    // .... constructeur destructeur.
      virtual void addOptions(std::vector<Option<???> >& optionList) {
        optionList.push_back(option1_);
        optionList.push_back(option2_);
      };
    };
    Vous l'aurez remarqué mon problème viens de la méthode addOptions(...) qui permet d'ajouter les options des classes concretes. Je ne sais pas comment faire pour avoir un vector contenant des "Option" de n'importe quel type.
    Je sais qu'en Java il y a un quelque chose du genre Option<?> qui permet d'avoir ce genre de comportement.
    Est-ce faisable en C++?

    Merci d'avance.

    PS: J'ai tenté de faire dériver Option<T> d'une classe AbstractOption puis de changer la méthode addOptions(std::vector<Option<???>*>& option) par
    addOptions(std::vector<AbstractOption*>& option) mais ceci m'oblige à faire des cast vers Option<?> avec le type toujours inconnu.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    je n'ai jamais tenté ça, mais peut-être que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class IOption
    {
      virtual ~IOption() {}
    };
    template< class T >
    class COption : public IOption
    {
    /*...*/
    };
    class AbstractOptions
    {
      void AddOptions (std::vector<IOption*> _vecOptions)=0;
    };
    sans conviction
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci pour ta contribution,
    Comme je l'ai dit dans mon PS: j'avais déjà tenter une approche de ce genre sans grand succés: il faut faire un cast de IOption vers COption<T> avec T qui n'est pas connu.

    Peut-être que mon architecture n'est pas correcte non plus...

  4. #4
    Membre expérimenté
    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
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par darkman19320 Voir le message
    Je sais qu'en Java il y a un quelque chose du genre Option<?> qui permet d'avoir ce genre de comportement.
    Est-ce faisable en C++?
    PS: J'ai tenté de faire dériver Option<T> d'une classe AbstractOption puis de changer la méthode addOptions(std::vector<Option<???>*>& option) par
    addOptions(std::vector<AbstractOption*>& option) mais ceci m'oblige à faire des cast vers Option<?> avec le type toujours inconnu.
    1) Ce que tu as fait s'appelle type erasure (tu pourrais faire des recherches sur ce nom pour avoir des références sur comment le faire dans les règles de l'art, mais je crois que tu avais le truc...)
    2) La question que tu dois te poser c'est: OK, je rassemble mes options dans le même conteneur, c'est que je veux les traiter uniformément. Quel service identique dans son interface mais implémenté de manière différenciée est-ce que j'attends de mes classes d'option. Même en Java (qui permet facilement de retrouver la bonne classe par réflexion au runtime) ce n'est pas un bon design de faire du downcast. La bonne pratique est de définir une interface commune avec implémentation polymorphe. Donc, la question à te poser est: quel(s) service(s) commun(s) est-ce que j'attends de mes différentes options, et quelle interface me permet de représenter pour toutes l'appel à ce ou ces services et la réponse.

  5. #5
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Je pensais avoir trouver une 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
     
    class Program;
     
    template<typename T>
    class Option
    {
    private:
      T value_;
    public:
      Option(const T& value) : value_(value) {};
      virtual ~Option(){};
      T& operator()() {
        return value_;
      };
     
      void pushOptionToProgram(const Program& p) {
        p.addOption(*this);
      };
    };
     
    class Program
    {
    public:
      Program(){};
      template<typename T>
      void addOption(const Option<T>& option)
      {
        cout << "option(): " << (option()) << endl;
      }
    };
    Seulement voila... ca compile pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ../main.cpp: In member function ‘void Option<T>::pushOptionToProgram(const Program&)’:
    ../main.cpp:95: error: invalid use of incomplete type ‘const struct Program’
    ../main.cpp:80: error: forward declaration of ‘const struct Program’
    Suis-je sur la bonne voie?

  6. #6
    Membre expérimenté
    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
    Points : 1 475
    Points
    1 475
    Par défaut
    Deux choses:
    1) pourquoi ton code ne compile pas:
    Tu utilise une fonction membre de Program dans la définition de la fonction pushOptionToProgram:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void pushOptionToProgram(const Program& p) {
        p.addOption(*this);
      };
    Dans ce cas tu ne peux pas utiliser de forward declaration, il faut la définition complète de la classe.
    Solution: séparation définition/implémentation dans des fichiers .h et .cpp ==> dans la définition d'Option (.h) tu ne mets que la forward declaration de Program, dans ton fichier cpp qui implémente les fonctions de la classe Option tu #include le fichier .h qui définit la classe Program pour avoir la définition entière de la classe. Dans le même esprit, le fichier .h qui définit la classe Program n'a besoin que de la forward declaration de la classe Option, pour l'implémentation c'est à voir en fonction du code...

    2)
    Suis-je sur la bonne voie?
    Ca depend de ce que tu veux faire de ces options après les avoir listées dans le program...là tu t'éloignes de la type erasure ... mais d'abord, que définit le paramètre de template T? La première question à se poser, c'est qu'ont les différentes classes d'options en commun (définition d'un nom pour les retrouver?, interface pour exploiter la valeur?), qu'est-ce qui diffère entre elles (stockage de la valeur? système de politiques?)? Quel est l'effet de l'enregistrement d'une option? Comment comptes-tu ensuite exploiter les options ? (simple lecture? fourniture d'un effet implémenté par l'option?)

  7. #7
    Membre expérimenté
    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
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par therwald Voir le message
    système de politiques?
    Un peu vite écrit. Disons, veux tu un design pattern "Strategy" (sous une même API, les options proposent différentes variantes d'algorithmes pour implémenter l'effet d'une option)

  8. #8
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    C'est bon je viens de réussir!!!
    Merci pour tout.
    Citation Envoyé par therwald Voir le message
    Solution: séparation définition/implémentation dans des fichiers .h et .cpp
    C'est ce que je viens de faire.

    Citation Envoyé par therwald Voir le message
    2) Ca depend de ce que tu veux faire de ces options après les avoir listées dans le program...
    Je voulais passer mes options à mon program pour qu'il les passe à boost program_option et lire à partir d'un fichier de configuration.

    J'ai réussi de la manière suivante:
    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
     
    template<typename T>
    class Option
    {
    private:
      T value_;
    public:
      Option(const T& value):value_(value){}
      virtual ~Option(){}
      T& operator()() {
        return value_;
      }
    };
     
    class Program
    {
    public:
      Program();
      virtual ~Program() {}
      template<typename T>
        void addOption(T& option)
        {
          std::cout << "old value: " << option << std::endl;
          std::cout << "option() = (T)2;" << std::endl;
          option = (T) 2;
          std::cout << "changed value: " << option << std::endl;
        }
    };
     
    class Options
    {
    protected:
      Options(){};
    public:
      virtual ~Options(){};
      virtual void pushAllOptionsToProgram(Program& program) = 0;
    };
     
    class BoundOptions : public Options
    {
    private:
      Option<double> epsilon_;
      Option<int> epsilonInt_;
    public:
      BoundOptions(): epsilon_(0.0), epsilonInt(0) {};
      ~BoundOptions() {};
      virtual void pushAllOptionsToProgram(Program& program) {
        program.addOption(epsilon_());
        program.addOption(epsilonInt_());
        cout << "isChanged? " << epsilon_() << endl;
      };
    };
    Ensuite pour accéder aux valeurs de mes données, je passe directement l'objet crée (BoundOption) à mes diverses fonctions.

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017

  10. #10
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci 3DArchi.
    Je ne l'avais ce lien.

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

Discussions similaires

  1. [Débutant] Créer une liste d'objets
    Par arngrimur dans le forum C#
    Réponses: 3
    Dernier message: 22/02/2017, 14h08
  2. Réponses: 1
    Dernier message: 30/03/2011, 22h27
  3. Réponses: 3
    Dernier message: 19/07/2010, 08h42
  4. Créer une liste d'objet spécifiques
    Par Lidden dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 03/02/2008, 10h26
  5. Créer une liste d'objets statiques dans une classe
    Par crossbowman dans le forum C++
    Réponses: 3
    Dernier message: 13/03/2006, 09h11

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