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éation d'objets par rapport à un ID


Sujet :

C++

  1. #1
    Membre habitué
    Homme Profil pro
    fdghg
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : fdghg
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 142
    Points
    142
    Par défaut Création d'objets par rapport à un ID
    Bonjour,

    J'ai une question sur l'orienté objet en C++, je souhaiterais crée un objet par rapport à son ID

    Par exemple :

    J'ai 3 classe fille qui contienne des id qui ne change jamais avec maClass::getId();

    Dans le main en gros j'aimerais crée l'objet en fonction du nombre que je lui envoi

    J'ai 3 class : id 1 4 et 6

    Si j'envoi 1 alors il crée la classe 1
    Et j'aimerais faire sa SANS if, ou switch, quelque chose de dynamique donc.

    Vous avez une idée vers quoi je pourrais me tourner ?

    Merci bien

  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,

    quelle est cette idée saugrenue ? Et ces conditions fantaisistes ?

    Si tu as des class class Class1; class Class2; .... alors tu peux t'en tirer avec des macros
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Class1;
    class Class2;
    #define CREATE_CLASS(id) Class##id
     
    int main()
    {
     CREATE_CLASS(1) myClass;
     CREATE_CLASS(2)* dynamicClass = new CREATE_CLASS(2);
    }
    Cependant:
    - cette idée est vraiment limite, je ne vois aucune raison sensée et logique à vouloir faire ça. Ceci est sûrement très bien et utilisé dans des langages de scripts comme php ou que sais-je, mais ne l'est pas en C++.
    - impossible de faire un CREATE_CLASS avec une variable en paramètre. Du coup c'est quelque chose d'on ne peut plus statique.
    - aucune notion d'orienté objet ici. Utiliser des class ne signifie pas orienté objet.

    Donc, avec une vraie expression du besoin, et la suppression de tes conditions fantaisistes (exit le "SANS if, ou switch, quelque chose de dynamique donc"), on pourra proposer une vraie solution.
    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 habitué
    Homme Profil pro
    fdghg
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : fdghg
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 142
    Points
    142
    Par défaut
    D'accord

    Donc je souhaite faire un protocole réseau avec des messages

    J'ai à peu pret 800 messages chaqu'un contenant un ID (1,2,3,4, .... 755,756 etc..)

    Quand mon serveur envoie un message, il envoie l'ID et donc j'aimerais crée le message en fonction de l'ID que je reçois

  4. #4
    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
    Un simple switch
    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.

  5. #5
    Membre habitué
    Homme Profil pro
    fdghg
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : fdghg
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 142
    Points
    142
    Par défaut
    C'est ce que je disait avec ma "condition fantaisiste". Je voudrais une autre méthode qu'un switch de 800 cases

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Hello

    Citation Envoyé par Bousk Voir le message
    quelle est cette idée saugrenue ? Et ces conditions fantaisistes ?
    Ce n'est pas si saugrenu, et c'est même un besoin qui peut revenir souvent.

    Je vais te montrer une technique pour faire cela nostrora, mais quelques mises en gardes:
    - Tu dois avoir une interface commune à toutes tes classes de messages.
    - Pèse bien la décision de vouloir implémenter et surtout maintenir 800 classes différentes. 800 ! Il y a peut-être une autre manière de s'y prendre, il faut voir avec des gens qui ont déjà implémenté des protocoles.
    - Ma technique se base sur le mécanisme d'initialisation statique. Ca fera tout de même 800 std::string stockées en statique dans ton exécutable/bibliothèque.

    Le principe est d'utiliser un singleton qui va servir de factory et dans lequel on va enregistrer nos classes à l'initialisation statique en lui donnant une fonction de construction. Avec un template et en acceptant de laisser les constructeurs des messages en accès public, le seul ajout du ClassID et la dérivation du template suffit à rendre la classe instanciable par son ID.


    Voici le code.
    Find me on github

  7. #7
    Membre habitué
    Homme Profil pro
    fdghg
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : fdghg
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 142
    Points
    142
    Par défaut
    Merci 1000 fois pour ce code. C'est exactement ce que je voulais. Je n'ai pas encore vue les singleton, je vais pouvoir découvrir sa!

    Que veux tu dire par 800 std::string ?
    les id's ne sont pas des string mais bien des nombres
    Je ne pense pas que ce soit grave

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par nostrora Voir le message
    Merci 1000 fois pour ce code. C'est exactement ce que je voulais.
    Alors pouce mon message pour me donner des points

    Citation Envoyé par nostrora Voir le message
    les id's ne sont pas des string mais bien des nombres
    Je ne pense pas que ce soit grave
    En effet, tu peux utiliser un int ou un unsigned int comme id. Comme ce sont des membres statiques des classes, ils occuperont de la place dans le segment données de ton exécutable. Pour 800 int, ça nous fait (800*4/1000) Mo = 3.2 Mo en plus dans ton exécutable/bibliothèque. Cela peut jouer si tu as des besoin de minimilisation de ton exécutable. Cela dit, avec un protocole qui gère 800 messages différents, difficile de faire très compact .
    Find me on github

  9. #9
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par nostrora Voir le message
    Je n'ai pas encore vu les singleton, je vais pouvoir découvrir ça!
    Attention à mon singleton, je n'ai pas protégé la copie ni l'assignement, ce qu'il faut faire normalement ! Je ne l'ai pas fait pour laisser le code le plus compact et le plus lisible possible.
    Find me on github

  10. #10
    Membre habitué
    Homme Profil pro
    fdghg
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : fdghg
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 142
    Points
    142
    Par défaut
    Désolé pour les fautes
    Oui j'ai fait les pouces :p

    Merci merci

  11. #11
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par nostrora Voir le message
    C'est ce que je disait avec ma "condition fantaisiste". Je voudrais une autre méthode qu'un switch de 800 cases
    A mettre au propre (mais le principe est quand même valide). Il ne requiert qu'une seule chose : que tes classes de message dérivent toutes de la même classe mère (pas forcément une mauvaise chose ; à voir si ça correspond à ton design - de toute façon si tu veux utiliser les objets en question, tu as besoin d'en connaître l'interface).

    Quelques pistes de mise au propre :
    * encapsuler dans un objet
    * les makers ne sont plus des fonctions, mais des objets (avec des propriétés comme le nom, ..., histoire d'avoir des infos supplémentaires pour le debug ou le runtime)

    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
     
    typedef msg_base_class *(*maker_func_type)(const msg_data&)
    typedef std::map<unsigned int id, maker_func_type> maker_map_type;
     
    maker_map_type maker_map;
     
    void add_maker(unsigned int id, maker_func_type func)
    {
        // add only if the id is not associated with an existing maker
        make_map_type::iterator_type it = maker_map.find(id);
        if (it == maker_map.end()) {
            maker_map[id] = func;
        } else {
            std::stringstream s; 
            s << "id " << id << " is already bound to a message maker";
            throw std::runtime_error(s.str());
        }
    }
     
    msg_base_class *make(unsigned int id, const msg_data& data)
    {
        make_map_type::iterator_type it = maker_map.find(id);
        if (it != maker_map.end()) {
           return it->second(data);
        }
        return NULL; // or nullptr in C++11
    }
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  12. #12
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Emmanuel Deloget puisque tu passes par là, j'aimerais savoir ce que tu penses de la technique que j'ai proposée à nostrora (et mise presque au propre dans un exemple).

    Nostrora: mon code nécessite quelques arrangements, protéger le singleton correctement, mettre de la constness où il faut. Je te conseille d'utiliser la technique sans la copier-coller directement pour bien comprendre comment ça fonctionne.
    Find me on github

  13. #13
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Emmanuel Deloget puisque tu passes par là, j'aimerais savoir ce que tu penses de la technique que j'ai proposée à nostrora (et mise presque au propre dans un exemple).
    C'est essentiellement la solution que je propose, avec des améliorations, donc je ne peux qu'en penser du bien

    Quelques points quand même :

    * le coté singleton n'est pas nécessaire selon moi (je pourrais utiliser le même mécanisme pour gérer deux types de messages dans deux factory différentes, pour plus de clarté).

    * l'utilisation du CRTP force l'intégration (implicite qui plus est) d'une seconde responsabilité dans la classe de gestion des messages. Il vaut mieux séparer la gestion du message de sa construction.

    * le lien que tu as mis entre l'objet constructeur et l'id - qui ne marchera que si l'objet constructeur n'est pas dans une librairie dynamique (a cause du static). Etant donné que l'id est une constante, il n'est pas nécessaire non plus (si besoin, l'id peut être accessible via une méthode ; puisque l'id est constant, il n'est pas nécessaire de lui associer une donnée - la méthode peut se contenter de le retourner)

    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
     
    struct maker_base
    {
        typedef unsigned int id_type;
        virtual id_type id() const = 0;
        virtual interface *make(const msgdata&) const = 0;
    };
     
    template <class C, maker_base::id_type ID>
    struct maker : maker_base
    {
        // if C++11 is used: 
        std::static_assert(std::is_base_of<interface, C>::value, 
            "template parameter C should inherit the 'interface' class");
     
        typedef C interface_type;
     
        virtual id_type id() const 
        { return ID; }
     
        // covariant return type
        virtual interface_type *make(const msgdata& data) const 
        { return new interface_type(data); }
    };
    L'utilisation se fait relativement simplement:

    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
     
    class factory
    {
    public:
       void register_maker(maker_base *maker)
       { m_classes.insert(std::make_pair(maker->id(), maker)); }
    };
     
    class my_message : public interface 
    { 
        ... 
    public:
        static const maker_base::id_type id = 10;
        ... 
    }
     
    // un seul typedef est nécessaire pour définir un nouveau maker
    typedef maker<my_message, my_message::id> my_message_maker;
     
    ...
    the_factory.register_maker(new my_message_maker());
    (le fait que my_message connaisse son id n'est pas abhérent - my_message peut être aussi utilisé pour construire le message à envoyer).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  14. #14
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    * l'utilisation du CRTP force l'intégration (implicite qui plus est) d'une seconde responsabilité dans la classe de gestion des messages. Il vaut mieux séparer la gestion du message de sa construction.
    Yes, j'y ai pensé après coup.

    Citation Envoyé par Emmanuel Deloget Voir le message
    * le lien que tu as mis entre l'objet constructeur et l'id - qui ne marchera que si l'objet constructeur n'est pas dans une librairie dynamique (a cause du static).
    Hum je ne suis pas sûr de ça car en l'occurrence, mon "objet" constructeur n'en est pas un mais est un pointeur de fonction de base, ce qui laisse la possibilité de distribuer tout ça dans plusieurs librairies, sans que la librairie qui le référence n'aie besoin de connaître l'objet. On peut promener des pointeurs de fonctions d'une librairie dynamique à une autre.

    Citation Envoyé par Emmanuel Deloget Voir le message
    * le coté singleton n'est pas nécessaire selon moi (je pourrais utiliser le même mécanisme pour gérer deux types de messages dans deux factory différentes, pour plus de clarté).
    C'est la plus grande source de réflexion pour moi: où mettre le code qui enregistre le maker dans la factory ?

    Dans mon cas, je propose de profiter de l'initialisation de l'id pour effectuer cette opération, de sorte que l'écriture de la classe seule suffit sans qu'on aie à l'ajouter manuellement dans une liste. De fait, n'importe quelle librairie dynamique qui se charge enregistre ses classes sans avoir à intervenir dans le code d'initialisation. Pas faisable sans singleton à mon avis, mais si tu as une idée je prend.

    Dans ton esprit, d'après ce que j'ai compris, la dépendance est dans l'autre sens et la factory est construite au dessus des classes, ayant donc besoin de toutes les connaître (ou au moins les makers) pour s'initialiser. Ce qui permet de se passer de singleton et d'avoir plusieurs factory.
    Find me on github

  15. #15
    Membre habitué
    Homme Profil pro
    fdghg
    Inscrit en
    Avril 2011
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : fdghg
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 66
    Points : 142
    Points
    142
    Par défaut
    Je vais encore un peu lire Penser en C++ Volume 1 Pour bien comprendre les notions que vous me proposer. Merci
    Eventuellement si vous avez des lecture à me proposer qui encadre bien les notions dont vous parler, ça m'interesse ! merci

  16. #16
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Tu veux de bonnes lectures? cherches les discussions de plus de trois pages dans ce forum et dans la sous-section langage

    Plus que dans les cours, tu y trouveras de (très) longs et instructifs débats.
    J'y ai appris beaucoup sur les subtilités de notions qui me paraissaient évidentes.

    Sinon, il y a toujours la section "cours"
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  17. #17
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Pour 800 int, ça nous fait (800*4/1000) Mo = 3.2 Mo en plus dans ton exécutable/bibliothèque. Cela peut jouer si tu as des besoin de minimilisation de ton exécutable. Cela dit, avec un protocole qui gère 800 messages différents, difficile de faire très compact .
    800 * 4 / 1024 = 3.125 Ko et non pas 3.2 Mo

  18. #18
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    800 * 4 / 1024 = 3.125 Ko et non pas 3.2 Mo
    Ha ha oui exact Ca vote en faveur de ma proposition cela dit
    Find me on github

Discussions similaires

  1. Création d'objet par appel de méthode
    Par Jean_Benoit dans le forum Langage
    Réponses: 2
    Dernier message: 15/08/2011, 18h11
  2. Réponses: 1
    Dernier message: 08/10/2009, 16h44
  3. Création d'objets "par lots"
    Par phplive dans le forum Langage
    Réponses: 75
    Dernier message: 10/12/2008, 22h02
  4. Réponses: 1
    Dernier message: 04/12/2008, 12h43
  5. Réponses: 8
    Dernier message: 23/11/2007, 17h46

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