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 :

[Objet] Nommage dynamique d'une classe


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Par défaut [Objet] Nommage dynamique d'une classe
    Bonjour,

    J'aimerais savoir s'il est possible en C++ d'instancier une classe à partir d'un nom provenant d'une variable.
    Habitué à PHP, je sais que c'est possible, l'idée serait de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string className = "maClasseFille";
    MaClasseMere uneInstance = maClasseFille.c_str()::getInstance();
    Pour ce que je connais de la souplesse du C++ je doute qu'une telle chose soit possible. Je me trompe ?
    Sinon : quelle solution donc permet de palier au problème ?

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Tu ne peux.

    Mais tu peux utiliser le Design Pattern "Factory", pour créer des classes créatrices.
    Et ensuite, te créer une map< string, Factory* >...

    C'est ce que font les MFC avec les macros de type DECLARE_DYNCREATE, par exemple.
    Sans compter COM, qui fait encore plus complexe, mais ne nécessite pas les MFC...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre confirmé Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Par défaut
    Bien,

    J'aurais au passage du préciser que je développe pour Linux (donc avec g++).

    Je pense reproduire le même principe en utilisant ce principe dans la classe mère :
    (ce code ne compile pas forcément, mais l'idée est derrière)

    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
     
    public class maClasseMere
    {
      public static getUneDeMesFilles(string sonPetitNom)
      {
        switch(sonPetitNom)
        {
           // ... on return la fille qui correspond au nom
        }
     
      }
     
    }
     
    maClasseMere uneFille = maClasseMere::getUneDeMesFilles("laCadette");
    Si j'ai bien compris le principe de factory, je serai tout de même forcé de "nommer" à un moment ou a un autre mes classes, dans le switch{} en l'occurence.

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    À cela près que switch() ne marche que sur les nombres.
    Typiquement, tu peux créer une map, par contre...

    Typiquement, cette map sera un singleton, et ainsi tu pourras la remplir dans le constructeur de ta factory...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre confirmé Avatar de raoulchatigre
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Mars 2004
    Messages : 99
    Par défaut
    Dammit, vilain switch !

    Typiquement, cette map sera un singleton, et ainsi tu pourras la remplir dans le constructeur de ta factory...
    Heu excuses moi, j'ai du mal à te suivre : une map singleton ?

    Bon, je crois que je veux aller trop vite en besogne, je vas commencer par faire fonctionner ma nouvelle structure avec des noms de classes en dur et je me pencherai sur l'option des factory ensuite.

    Je recréerai un thread si besoin, merci en tout cas !

    PS: Heu je clique sur délestage ou résolu ?

  6. #6
    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,

    Le singleton est, tout simplement, un modèle de conception qui s'assure qu'il n'existera jamais qu'une instance de l'objet...

    Comme il est fréquent qu'il y ait plusieurs types d'objets totalement différents dont on veuille n'avoir jamais qu'une seule instance maximum pour chacun des type, le plus facile est d'avoir recours à un singleton modèle, et au CRTP:
    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
     
    template <class T>
    class Singleton
    {
        public:
            static T& getInstance()
            {
                if(!instance)
                    instance=new T;
                return instance;
            }
            static void destroy()
            {
                 delete instance;
                 instance=NULL
            }
        protected:
            Singleton(){}
            ~Singleton() {}
        private:
            T* instance;
             /* interdiction de la copie */
             Singleton(Singleton&);
             void operator= (Singleton&);
    };
    template <class T>
    T* Singleton::instance=NULL;
    Sur base de ce singleton, nous allons créer un type qui va contenir l'ensemble des factories qui peuvent nous intéresser.

    Cela prendra 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
    class FactoryHolder: public Singleton<FactoryHolder>
    {
        public:
           /* mise en place du CRTP */
           friend class Singleton<FactoryHolder>;
           /* permet d'ajouter une nouvelle factory */
            void registerFactory(const std::string& fn, Facotry* fac)
            {
                 items.insert(std::make_pair(fn, fac);
            }
            /* permet de récupérer une factory */
            Factory* getFactory(const std::string& name)
            {
                std::map<std::string, Factory*>::iterator it=items.find(name);
                if(it==items.end())
                    return NULL;
                return (*it).second;
            }
            /* permet de supprimer une factory (si c'est dans tes intentions ;) */
            void unRegisterFactory(const std::string& name)
            {
                std::map<std::string, Factory*>::iterator it=items.find(name);
                if(it!=items.end())
                {
                    delete (*it).second;
                    items.erase(it);
                }
            }
        private:
            std::map<std::string, Factory*> items;
            FactoryHolder(){}
            ~FactoryHolder()
            {
                for(std::map<std::string, Factory*>::iterator it= items.begin();
                     it!=items.end();++it)
                    delete (*it).second;
            }
            /* copie interdite */
            FactoryHolder(FactoryHolder&);
            void operator=(FactoréHolder&);
    };
    A l'utilisation, cela se passera à peu pres comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    /*Chaque fois que tu veux insérer une nouvelle factory dans la map */
    FactoryHolder::getInstance().registerFactory("le_nom",new lanouvelfactory());
    /* chaque fois que tu veux supprimer une factory */
    FactoryHolder::getInstance().unRegisterFactory("le_nom_a_supprimer");
    /* caque fois que tu veux utiliser une factory */
    FactoryHolder::getInstance().getFactory("le_nom_recherche").laMethodeDinterface();
    (il va de soi que "le_nom","le_nom_a_supprimer" et"le_nom_recherche" peuvent être des variables de type std::string ou tout type disposant d'une méthode de conversion vers celles-ci

    Cela pourrait donc prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::stringstream ss;
    std::string c1;
    int i2;
    std::string c3;
    /* récupération des trois données... ou tu le veux */
    ss<<c1<<p2<<c3;
    FactoryHolder::getInstance().registerFactory(ss.str(),new lanouvelfactory());
    Evidemment, toutes les factories devront, pour bien faire, dériver d'une classe "Factory" qui présentera l'interface qu'on compte utiliser

    PS: tu peux cliquer sur résolu, délestage, c'est plutôt pour demander le nettoyage du fil de discution
    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

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 15/02/2013, 23h27
  2. [PHP 5.2] Faire d'un objet un membre d'une classe
    Par Huntress dans le forum Langage
    Réponses: 3
    Dernier message: 31/01/2009, 00h59
  3. Objet de base d'une classe derivée
    Par Seth77 dans le forum C#
    Réponses: 7
    Dernier message: 03/05/2007, 13h39
  4. [ClassLoader] Chargement dynamique d'une classe -> problème avec packages !
    Par ymerej dans le forum API standards et tierces
    Réponses: 9
    Dernier message: 31/05/2006, 21h37
  5. [RegEx] Trouver les appels statique et dynamique d'une class
    Par jeff_! dans le forum Langage
    Réponses: 8
    Dernier message: 07/04/2006, 16h31

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