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 :

comment surcharger les paramètres d'une methode virtual


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut comment surcharger les paramètres d'une methode virtual
    Bonjour,

    Je suis confronter sur un problème depuis maintenant une semaine et j'ai bo chercher sur internet je n'arrive pas à trouver une solution de mon problème.

    Mon Problème se situe sur la surcharge du nombre de paramètre d'une fonction.

    J'ai une classe C_Mesh :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    	class SILVERENGINE_API C_Mesh{
    		public:
    			// ... autre méthodes de la classe
     
    			virtual C_Mesh* GetThisPtr() { return this; } 
     
    			virtual void Create(C_Mesh& p_mesh){};
     
    	};
    et j'ai également une classe C_Plane :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
            class SILVERENGINE_API C_Plane{
    		public:
    			// ... autre méthodes de la classe
     
     
    			virtual C_Plane* GetThisPtr() { return this; } 
     
    			virtual void Create(C_Mesh& p_mesh, float[] p_size, int[] p_nbSubPlane);
     
     
    	};
    Pour finir j'ai un MeshManager :

    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
     
    /**
            *       \class   C_MeshManager
            *       \extends C_Singleton<C_MeshManager>
            */
    	class SILVERENGINE_API C_MeshManager : public C_Singleton <C_MeshManager>{
    		MAKE_SINGLETON(C_MeshManager)
    		/**
                    * \publicsection
                    */
    		public:
     
    			template<TMeshType p_type, typename ... Args>
    			C_Mesh* Create(std::string const& p_name,  Args&& ... p_args){
    				C_Mesh* newMesh;
     
    				auto meshCreate = MeshFactory.Create(p_type)->GetThisPtr(); // <-- meshCreate = C_Plane* pour le test
    				meshCreate->Create(newMesh, p_args);
    				return newMesh;
    			}
     
    		/**
                    * \privatesection
                    */
    		private:
    			C_MeshManager();
    			~C_MeshManager();
    	};
    lorsque je compile tous se passe bien mais lorsque j'exécute le programme cela m'indique :

    Erreur 4 error C2660: 'SilverEngine::C_Mesh::Create'*: la fonction ne prend pas 3 arguments c:\users\ksta\desktop\dll\sources\silverengine\core\c_meshmanager.h 47 1 TestDLL
    voici l'utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
            float size[]  = { 5.0f, 5.0f };
    	int subPlane[] = { 0, 0 };
    	m_testMesh = MeshManager.Create<TMeshType::MESH_PLANE>("testPlane", size, subPlane);
    Se que j'aimerais c'est obliger l'utilisateur à redéfinir la fonction Create dans les sous class de Mesh et si possible rajouter des arguments.

    J'ai essayer de pas les mettre virtual, de définir using C_Mesh::Create; devant la fonction de C_Plane mais aucun résultat imposible d'exécuter.

    Si quelqu'un aurai une solution je le remercie d'avance.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 631
    Points : 10 558
    Points
    10 558

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Merci pour le lien mais si je peut me permettre car je n'arrive pas trop à comprendre la solution.

    Il faut que je créer une classe paramètre qui stockera le type et le nom et après je passe un tableau de la class parametre dans la fonction c'est sa?

    Si c'est le cas est-ce que je pourrais utiliser différents types du coup?

    Merci encor pour ton aide

  4. #4
    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
    Salut,

    Quand tu exécutes ton code en mode debug pas à pas, qu'obtiens tu comme type pour meshCreate? Il se peut que ta factory ne crée pas le bon type d'objet.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Salut,

    Merci pour ton aide.

    Le problème c'est que le code s'exécute pas en mode debug et donc je n'arrive pas au point d'arret.

    par contre si je rajoute ... dans la fonctin de la class C_Mesh la il s'exécute:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
            class SILVERENGINE_API C_Mesh{
    		public:
    			// ... autre méthodes de la classe
     
    			virtual C_Mesh* GetThisPtr() { return this; } 
     
    			virtual void Create(C_Mesh& p_mesh, ...){};
     
    	};
    avec ce code mon factory me sort bien un C_Plane mais ne rentre pas dans la foncyion générate de C_Plane mais de C_Mesh.

    J'avais sinon penser faire un attribut qui contiendrais un délégate mais est-ce propre?

  6. #6
    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
    Le problème vient du fait que tu ne fais pas d'héritage de C_Mesh par C_Plane. Du coup, tu appelles toujours la méthode Create de C_Mesh. Par contre, c'est le plus grand des hasard que ton programme compile et encore plus qu'il s'exécute!

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Ha autant pour moi c'est une erreur quand j'ai retaper mes classe dans le message.

    Ma class C_Plane hérite bien de C_Mesh

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
             class SILVERENGINE_API C_Plane : public C_Mesh{
    		public:
    			// ... autre méthodes de la classe
     
     
    			virtual C_Plane* GetThisPtr() { return this; } 
     
                            using C_Mesh::Create;
    			virtual void Create(C_Mesh& p_mesh, float[] p_size, int[] p_nbSubPlane);
     
     
    	};
    j'ai essayer également avec using C_Mesh::Create; que j'ai vue sur internet mais sans résultat toujours la même erreur

  8. #8
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Est-ce que quelqu'un aurai une exemple simple avec deux class test qui fonctionnerais par hasard pour que j'arrive à comprendre comment résoudre mon problème qui est de surcharger les arguments dans la définition d'une fonction virtuel dans une class enfant?

    car j'ai bo chercher sur internet je n'arrive pas à trouver un exemple simple qui expliquerais la solution.

    Merci d'avance.

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut :

    Tu peux surcharger une fonction virtuelle, comme n'importe quelle autre fonction, pour autant que tu le faces au niveau de la classe de base. Il n'y a rien qui t'en empêche, du moins, au niveau du langage.

    Il n'y a aucune raison pour que le code qui suit ne compile pas
    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
    class Base{
    public;
        virtual ~Base();
        void foo(int i){
            // blabla
            foo();
            // truc
        }
        void foo(double d){
            // blabla
            foo();
            // truc
        }
        virtual void foo();
    };
    Et ce, même si la version virtuelle prend des paramètres (c'est juste peut etre plus complexe au niveau des surcharges pour s'assurer de fournir les paramètres à la version virtuelle).

    Cependant le fait de pouvoir le faire au niveau du langage ne signifie pas forcément qu'il faille d'un point de vue conceptuel.

    Car il faut bien être conscient du fait que toutes les surcharge de ta fonction devront être considérées comme "des propriétés prouvables de l'objet" au sens du LSP, ce qui implique que toutes ces surcharges devront avoir du sens au niveau des classes dérivées. Et ca, ca pourrait rapidement commencer à poser quelques problèmes lorsque tu voudras rajouter des classes dérivées.

    D'un autre coté, tu pourrais te dire "c'est pas grave : j'ajoute les surcharges qui m'intéressent au niveau des classes dérivées". Ce serait beaucoup mieux accepté au niveau du LSP, car la classe dérivée ne ferait qu'étendre l'interface de la classe de base, mais cela risque quand même de poser un très léger problème : la surcharge de la fonction ne sera accessible... qu'aux objets étant spécifiquement connus comme étant du type dérivé et sera tout à fait inaccessibles aux objets connus comme étant du type de base.

    La question à se poser en priorité est donc : sous quelle forme mes différents objets seront-il principalement (comprend : dans la plus grande partie du code) connus en tant que type de base ou en tant que type dérivé

    Et, si la réponse à cette question est "en tant que type de base", la très grosse question qu'il faudra te poser est : quelle mécanique me permettant de connaitre les différents objets dont je dispose comme étant de leur type réel (dérivé) au lieu de les connaitre comme étant du type de base vais-je mettre en place

    Si tu trouves une réponse satisfaisante à cette question, alors, vas-y. Après tout, il existe pas mal de solutions pour résoudre ce genre de problème Mais, si tu ne trouves pas de réponse satisfaisante, tu devrais sans doute, dans l'ordre:
    1. t'interroger sur la nécessité absolue de disposer des différentes surcharges
    2. t'interroger sur le respect du DIP :typiquement, les paramètres supplémentaires, cela me fait tout simplement penser à une abstraction manquante (à condition, bien sur, d'avoir une approche orientée service et non une approche orientée donnée)
    3. t'interroger sur le respect du LSP au niveau de l'héritage
    4. t'interroger sur le respect du SRP : vu que la fonction a besoin de plus de paramètres, ne commence-t-elle pas tout doucement à en faire plus que ce qu'elle ne devrait Pire encore : n'est-ce pas tout bonnement ta classe qui commence à en faire un peu trop


    TIP : Si tu penses au transtypage, oublie cette idée tout de suite... cela ne ferait que dresser un mur dans lequel tu foncerais à la première évolution à cause du non respect de l'OCP
    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

  10. #10
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Salut,

    merci pour cette explication qui d'un coup me fait réfléchir pas mal

    La question à se poser en priorité est donc : sous quelle forme mes différents objets seront-il principalement (comprend : dans la plus grande partie du code) connus en tant que type de base ou en tant que type dérivé
    Dans la plus part du code j'utiliserais la class de base mais chaque Type dérivant de cette classe aura des paramètres différent 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
     
     
    class Mesh{
    public;
     
    };
     
    class Plane : public Mesh{
        public:
            void Create(Mesh& p_mesh, float[] p_size, int[] p_subDivider);
        protected:
            float[2] m_size;
            int[2]    m_subDiviser;
    };
     
     
    class Circle : public Mesh{
        public:
            void Create(Mesh& p_mesh, float p_radius);
        protected:
            float m_radius;
    };
     
    class Cylindre ....
    class Cone .....
     
    //etc...
    en faite selon le type prédéfinie il y aura des paramètres en plus que pour le moment je connait pas car je sais pas encor tous les type que je vais faire et donc j'avais penser à la surcharge des argument pour faire cela qui me paraissais plus simple en théorie

    Si tu trouves une réponse satisfaisante à cette question, alors, vas-y. Après tout, il existe pas mal de solutions pour résoudre ce genre de problème Mais, si tu ne trouves pas de réponse satisfaisante, tu devrais sans doute, dans l'ordre:

    t'interroger sur la nécessité absolue de disposer des différentes surcharges
    t'interroger sur le respect du DIP :typiquement, les paramètres supplémentaires, cela me fait tout simplement penser à une abstraction manquante (à condition, bien sur, d'avoir une approche orientée service et non une approche orientée donnée)
    t'interroger sur le respect du LSP au niveau de l'héritage
    t'interroger sur le respect du SRP : vu que la fonction a besoin de plus de paramètres, ne commence-t-elle pas tout doucement à en faire plus que ce qu'elle ne devrait Pire encore : n'est-ce pas tout bonnement ta classe qui commence à en faire un peu trop
    la en effet je me demande maintenant avec toute tes explication claire si j'ai pas un problème de conception.

    mon bute était de rendre transparent l'initialisation des différents type par le biais d'une seul fonction du MeshManager se qui m'aurais éviter de faire ceci à chaque fois dans mon code :

    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
     
     
    C_Mesh* plane = MeshFactory.Create(TMeshType::MESH_PLANE);
    plane->SetSize(2.0f, 2.0f);
    plane->SetSubDiviser(0,0);
    plane->generateBuffers(); // génère le buffer de vertices et le buffer d'index
     
    //////////////////////////////
    // avec le MeshManager
    float[2] sizePlane = { 2.0f, 2.0f };
    int[2] subDiviser  = { 0, 0 };
     
    C_Mesh* plane = MeshManager.Create<TMeshType::MESH_PLANE>("plane_Test", sizePlane ,  subDiviser  ); 
     
    C_Mesh* circle = MeshFactory.Create(TMeshType::MESH_CIRCLE);
    circle ->SetRadius(2.0f);
    circle ->generateBuffers(); // génère le buffer de vertices et le buffer d'index
     
    //////////////////////////////
    // avec le MeshManager
    C_Mesh* circle = MeshManager.Create<TMeshType::MESH_CIRCLE>("plane_Test", 2.0f  );
    Et, si la réponse à cette question est "en tant que type de base", la très grosse question qu'il faudra te poser est : quelle mécanique me permettant de connaitre les différents objets dont je dispose comme étant de leur type réel (dérivé) au lieu de les connaitre comme étant du type de base vais-je mettre en place
    Pour l'instant j'avais mis une variable qui stock le type de Mesh qui me permettais de savoir quelle type c'est mais du coup suit à tes explications je me demande est-ce que je suis vraiment bien partie dans ma réflexion

    car je suis partie dans l’optique que chaque type dérivée avec des paramètres qui lui était propre mais si je veux rajouter une variable d'un type par exemple pour x raison ma fonction surcharger du coup n'est plus bonne

    Un autre problème qui se pose c'est que à chaque fois que j'aurais un type avec la fonction Create() différente, il va falloir que je la rajoute dans la class de base pour pouvoir l'utiliser dans le nouveau type et du coup ce n'est plus automatique

    c'est plus complexe que je pensais

    aurais tu une piste à m'orienter pour résoudre ce problème du coup?

    car je ne vois pas d'autre solution pour pouvoir rendre automatique l’initialisation des différents type le plus transparent possible.

    Merci encor pour cette explication.

  11. #11
    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
    Il y a plusieurs points qui me chiffonent dans ton implémentation: tu utilises une factory pour créer tes objets (bien!) mais dans chacun de tes objets, tu as une méthode Create. Quel est le but de cette méthode? Peut-être est-elle mal nommée?

    Sinon voici un petit exemple pour de la surcharge de fonctions virtuelles dans les classes filles:

    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
    #include<iostream>
     
    class Base
    {
    public:
       virtual void print() const
       {
           std::cout << "Base" << std::endl;
        }
    };
     
    class ChildA : public Base
    {
    public:
       using Mesh::print;  // On souhaite garder le comportement par défaut de la méthode print
     
       virtual void print(int v)
       {
           std::cout << "ChildA: " << std::endl;
        }
    };
     
    class ChildB : public Base
    {
    public:
    // Nous ne faisons pas appel à using et nous ne surchageons pas la méthode print de Base.
     
      virtual void print(int v)
      {
          std::cout << "ChildB: " << std::endl;
       }
    };
     
    int main(int argc, char* argv[])
    {
       ChildA a;
       a.print(); // Affiche Base
       a.print(42); // Affiche ChildA: 42
     
       ChildB b;
       // b.print(); // ne compile pas car cette méthode n'est pas explicitement définit dans ChildB. Vu que l'on peut avoir de l'héritage multiple avec des noms de méthodes identiques, il faut indiquer explicitement quelle méthode de quelle classe il faut utiliser.
       b.Base::print(); // Affiche Base
       b.print(42); // Affiche ChildB: 42
     
       return 0;
    }
    Edit: Petit conseil: quand tu compiles, mets les niveaux des Warnings au maximum (pour clang/gcc -Wall -Wextra). Ça te permettra justement de voir que tu "caches" en surchargeant une méthode virtuelle.

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Sauf que, si c'est juste une fonction "create" qui a besoin de paramètres différents, j'ai le plaisir et le devoir de t'annoncer que... tu n'a aucun besoin de cette fonction! Ce dont tu as besoin, c'est du constructeur, qui n'est en aucun cas virtuel

    De plus, tu prends la peine de créer une fabrique... La fabrique n'utilise par défaut que des fonctions qui ne seront pas virtuelles, et qui peuvent donc sans aucun problème être surchargée... Surcharge les fonctions de ta fabrique, et profites-en (si, sait-on jamais, plusieurs types d'objets nécessitent un nombre d'argument de même type identique) pour vérifier que le type que tu as introduit est "compatible" avec le nombre et le type des arguments que tu as transmis à ta fabrique, sous la forme d'une assertion vu que si ce n'est pas le cas, c'est typiquement une connerie de la part du développeur qui a fait appel à la fabrique
    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

  13. #13
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Salut,

    Merci pour toutes ces explications

    @darkman19320 :
    Il y a plusieurs points qui me chiffonent dans ton implémentation: tu utilises une factory pour créer tes objets (bien!) mais dans chacun de tes objets, tu as une méthode Create. Quel est le but de cette méthode? Peut-être est-elle mal nommée?
    Cette fonction à été faite justement car je ne savais pas comment je pouvais faire pour enregistrer mes différentes instance avec des paramètres variable dans mon Factory.

    voici mon Factory de Base :

    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
     
            template <class Obj, class Key = std::string> 
    	class C_Factory{		
    		/**
                    * \publicsection
                    */
    		public:
    			typedef Obj* ObjPtr;
    			typedef std::map<Key, ObjPtr> mapInstFactory;
     
    			C_Factory() {
    				m_mapInstance = std::map<Key, ObjPtr>();
    			}
    			~C_Factory() {}
     
     
    			void Register(Key p_key, ObjPtr p_instance){
    				if (m_mapInstance.find(p_key) == m_mapInstance.end()){
    					m_mapInstance[p_key] = p_instance;
    				}
    			}
     
     
    			void Unregister(Key const & p_key){
    				mapInstFactory::iterator l_it = m_mapInstance.find(p_key);
     
    				if (l_it != m_mapInstance.end()){
    					m_mapInstance.erase(p_key);
    				}
    			}
     
    			ObjPtr Create(Key const & p_key){
    				ObjPtr l_return;
     
    				mapInstFactory::iterator l_it = m_mapInstance.find(p_key);
     
    				if (l_it != m_mapInstance.end()){
    					l_return = ((*l_it).second)->clone();
    				}
    				return l_return;
    			}
     
    		protected:
    			mapInstFactory m_mapInstance; /**< \brief contient toutes les instance enregistrer dans le Factory */
    	};
    et voici comment j'enregistre mes différentes instance dans le constructeur de MeshFactory :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
           /**
            *       \fn             public void C_MeshFactory()
            *       \brief          Constructor - Permet de créer tous les instances générale Mesh existant dans le factory
            */
    	C_MeshFactory::C_MeshFactory() : C_Factory<C_MeshGenerator, TMeshType>(){
    		Register(TMeshType::MESH_PLANE, new C_Plane());
                    // pour le moment il n'y a que C_Plane mais il y aurai les autres
    	}
    Le problème que je rencontrais était de pouvoir passer les paramètres lorsque je l'enregistre dans le constructeur du Factory mais suite à vos intervention je pense que j'ai mal conçu ceci également.

    @koala01:

    De plus, tu prends la peine de créer une fabrique... La fabrique n'utilise par défaut que des fonctions qui ne seront pas virtuelles, et qui peuvent donc sans aucun problème être surchargée... Surcharge les fonctions de ta fabrique, et profites-en (si, sait-on jamais, plusieurs types d'objets nécessitent un nombre d'argument de même type identique) pour vérifier que le type que tu as introduit est "compatible" avec le nombre et le type des arguments que tu as transmis à ta fabrique, sous la forme d'une assertion vu que si ce n'est pas le cas, c'est typiquement une connerie de la part du développeur qui a fait appel à la fabrique
    Désoler si je n'arrive pas trop à comprendre mais pour vérifier le nombre et le types il faudrait que j'ai un switch pour vérifier toutes les possibilité des différents types qui dérive exemple de Mesh :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
         C_Cercle(float p_radius);
         C_Plane(float[] p_size, int[] p_subDiviser)
         C_Cylinder(float p_radius, float p_width)
         C_Cone(float[] p_radius, float p_size)
         // etc....
    du coup je vois mal comment je doit fair pour rendre cela possible sans que j'ai à rajouter dans le Factory la condition des arguments si je rajoute un nouveau type?

    merci pour vos explication et votre aide je pense que en effet j’étais mal partie donc je vais supprimer la fonction create et trouver un moyen de passer les argument pour enregistrer une instance

  14. #14
    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
    Ta fabrique (C_Factory) fait trop de choses: elle doit juste se contenter de créer les objets.
    Voici une implémentation toute bête d'une Fabrique qui prend un nombre arbitraire d'arguments:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<typename Type>
    class Factory
    {
    public:
         template<typename... Arg>
         Type* create(Arg... a)
         {
            Type* v = new Type(a...);
            return v;
         }
    };
    Ce code n'est pas testé et surtout il faudra faire attention à la libération de la mémoire. Libre à toi d'utiliser des pointeurs intelligents.

    Pour ce qui est du stockage des objets créés, tu peux utiliser un manager.

    Voici un 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
     #include <map>
     
    template<typename Type, typename Key>
    class Manager
    {
    public:
         void add(const Key & key, const Type & obj)
         {
             m_objs[key] = obj;
         }
     
    private:
       std::map<Key, Type> m_objs;
    };
     
    class Plane
    {
    public:
        Plane(float a=0, float b=0, float c=0, float d=0) : m_a(a), m_b(b), m_c(c), m_d(d)
        {}
     
    private:
       float m_a, m_b, m_c, m_d;
    };
     
     
    int main(int, char*[])
    {
       Factory<Plane> planeFactory;
       Manager<Plane, int> planeManager;
     
       Plane * plane1 = planeFactory(1,2,3,4);
       planeManager.add(0, *plane1);
       Plane * plane2 = planeFactory(1,2,3);
       planeManager.add(0, *plane2);
     
       delete plane1;
       delete plane2;
     
      return 0; 
    }
    Ce code est largement optimisable: ton exercice du week-end

  15. #15
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Ta fabrique (C_Factory) fait trop de choses: elle doit juste se contenter de créer les objets.
    Voici une implémentation toute bête d'une Fabrique qui prend un nombre arbitraire d'arguments:
    ha bon? Je pensais que le rôle d'un factory était de créer des instances enregistrer.

    du coup avec cet exemple je me retrouverais avec autant de factory et de manager que de type dérivé du coup faudra que je stock tous les factory et tous les Manager dans une autres class pour rendre ceci automatique non?

    Je suis un peu perdu avec cette explication.

    Ce code est largement optimisable: ton exercice du week-end
    en effet j'ai pas mal de chose à faire pour cette exercice

  16. #16
    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
    En fait, tu dois juste stocker les Manager. Tu n'as pas besoin de sauvegarder les Factory. Leur rôle est juste de créer mais pas de stocker les données (voir ici)

    En gros, dès que tu as besoin de créer un objet, tu crées ta fabrique puis tu stockes tes objets dans ton manager.

  17. #17
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Je pensais que le rôle d'un factory était de créer des instances enregistrer
    Je pense qu'il y a confusion entre une factory et le prototyping.
    Le prototyping est une manière de faire une factory mais n'est pas la seule.
    Et quand on commence à avoir des constructions complexes, l'utilisation d'un DP builder à la place ou en plus du prototyping permet de gérer des initialisations complexes.

  18. #18
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2015
    Messages : 58
    Points : 44
    Points
    44
    Par défaut
    Salut,

    désoler du retard j'ai enfin réussie à pouvoir travailler dessus et j'ai réussie à faire mon manager et factory correctement grâce à vous

    Merci à vous j'ai pas mal appris grâce à mon problème.

    Maintenant j'en est un autre mais avec la création de matrix de projection et de vue.

    Je vais ouvrir un nouveau sujet merci encore

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

Discussions similaires

  1. comment exporter les resultats d'une methode vers un textbox
    Par Khalid.bounouader dans le forum C#
    Réponses: 2
    Dernier message: 23/08/2008, 08h20
  2. Properties : comment spécifier les paramètres d'une property ?
    Par guilhemr dans le forum Collection et Stream
    Réponses: 9
    Dernier message: 21/04/2008, 13h57
  3. comment modifie les arguments d'une methode !
    Par lenetfm dans le forum Débuter avec Java
    Réponses: 7
    Dernier message: 18/03/2008, 16h44
  4. Comment configurer les paramètres d'une S-function
    Par karamellati dans le forum Simulink
    Réponses: 3
    Dernier message: 29/08/2007, 12h00
  5. Réponses: 11
    Dernier message: 06/09/2006, 12h48

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