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 :

Passage d'un objet générique en paramètre


Sujet :

C++

Vue hybride

lodacom Passage d'un objet générique... 19/05/2013, 14h32
Flob90 Il n'y a pas grand chose à... 19/05/2013, 16h26
koala01 Salut, Le monsieur te dit... 19/05/2013, 16h30
lodacom Bonjour, Merci de vos... 19/05/2013, 17h36
koala01 A moins d'utiliser le... 19/05/2013, 18h11
lodacom Conversion non viable 19/05/2013, 19h26
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    PHP + JAVA
    Inscrit en
    Mars 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : PHP + JAVA

    Informations forums :
    Inscription : Mars 2009
    Messages : 65
    Par défaut Passage d'un objet générique en paramètre
    Comme il est conseillé dans la FAQ de développez, j'ai déclaré mes .h et mes .cpp dans un seul fichier (ce qui m'a permis de résoudre pas mal de problèmes ). Mais maintenant il me reste un problème que je n'arrive pas à résoudre. C'est le passage d'un objet générique en paramètre d'une de mes fonctions (je le fait dans plusieurs de mes fonctions).
    Voici ce que je fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    template <class G,class S,class A>
    GenericAretes<G,S,A>::GenericAretes(G* p_arete_dans,S* p_somm1,S* p_somm2){
        num++;
    	stringstream s;
        s << "A" << num;
    	nom_arete=s.str();
        arete_dans=p_arete_dans;
    	somm1=p_somm1;
    	somm2=p_somm2;
        somm1->setSommet_dans(p_arete_dans);
        somm2->setSommet_dans(p_arete_dans);
        somm1->addArete(this);//erreur de compile ici
    }
    Je n'obtiens pas d'erreur de syntaxe, par contre ça plante quand je compile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    GenericAretes.h:55:21: Cannot initialize a parameter of type 'GenericLiens *' with an rvalue of type 'GenericAretes<GenericReseaux, GenericNoeuds, GenericLiens> *'
    (GenericLiens hérite de GenericAretes et concrétise cette dernière).
    J'ai essayé de trouver des réponses (passer par des cast et tout rien à faire) un peu partout mais impossible les rapprocher de mon problème.
    Voici ma fonction addArete:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template <class G,class S,class A>
    void GenericSommets<G,S,A>::addArete(A* p_arete){
    	aret_incidents.push_back(p_arete);
    }
    et "aret_incidents est un vector déclaré ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vector<A*> aret_incidents;
    Informations supplémentaires: je compile avec l'IDE XCode (qui prend en charge la dernière version du compilateur g++) de MAC OS X.
    Voilà si vous pourriez m'aider ça serait vraiment super. Merci d'avance.

  2. #2
    Membre Expert

    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 : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Il n'y a pas grand chose à faire, l'erreur est une erreur de conception. Ton objet this est de type GenericAretes<GenericReseaux, GenericNoeuds, GenericLiens>* pourquoi une fonction qui attend un GenericLiens* l'accepterait ? Un objet de type GenericAretes<GenericReseaux, GenericNoeuds, GenericLiens> n'est pas un objet de type GenericLiens, c'est l'inverse (grâce à ton héritage).

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    Salut,

    Le monsieur te dit qu'il ne sait pas comment convertir un pointeur sur un objet de type GenericAretes<A, B, C> en un pointeur vers un objet de type GenericLiens.

    Cela semble logique lorsque l'on sait que GenericLiens hérite de GenericArretes car la substituabilité permet de faire passer un (pointeur vers un) objet du type dérivé pour un (pointeurs vers un) objet du type de base.

    Par contre, il est tout à fait impossible d'utiliser la substituabilité pour récupérer un (pointeur sur un ) objet du type dérivé au départ d'un (pointeur sur un) objet du type de base et ce pour plusieurs raisons:

    Si le type dérivé connait le type de base, le type de base n'a par contre aucune connaissance du type dérivé, et n'a normalement pas à en avoir.

    Il peut y avoir plusieurs types dérivés d'un seul et même type de base, or, on connait l'objet pointé comme étant du type de base... Pour pouvoir récupérer le type réel de l'objet, il faudrait... qu'on ait la certitude d'essayer de récupérer le bon type réel, et cette certitude ne peut être acquise que si tu dis explicitement au compilateur de convertir ton type de base en type dérivé (static_cast ou dynamic_cast).

    Mais attention, à ce moment là, tu as vraiment intérêt à... etre sur de ton coup car si tu essaye de convertir ton objet "passant pour être" de type A en un objet de type B alors que c'est en réalité un objet de type C, tu coures à la catastrophe

    Tout cela pour dire que tu as, en gros, deux (allez, trois) solutions:

    Soit tu change le type du pointeur que tu essayes d'initialiser pour qu'il corresponde au type de base.

    Soit tu force le transtypage du pointeur obtenu en argument en un pointeur du type dérivé (static_ ou dynamic_ cast)

    Soit enfin tu crées une indirection supplémentaire qui te permettra d'utiliser le double dispatch afin d'être sur du type réel de l'objet pointé.
    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

  4. #4
    Membre confirmé
    Homme Profil pro
    PHP + JAVA
    Inscrit en
    Mars 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : PHP + JAVA

    Informations forums :
    Inscription : Mars 2009
    Messages : 65
    Par défaut
    Bonjour,
    Merci de vos réponses si rapides. Pour répondre à koala01, la première solution a priori ne me convient pas puisque mon paramètre de "addArete" est sensé rester générique. Et d'ailleurs, c'est qui n'est pas très logique, un paramètre qui est générique est sensé accepté tous les types des classes qui dérivent "GenericAretes" là j'avoue je ne comprend pas très bien .
    Pour ce qui est de la deuxième solution, comme tu le dit si bien:
    Mais attention, à ce moment là, tu as vraiment intérêt à... être sur de ton coup car si tu essaye de convertir ton objet "passant pour être" de type A en un objet de type B alors que c'est en réalité un objet de type C, tu coures à la catastrophe
    Et malheureusement je vais avoir une autre classe (qui va s'appeler GenericLiaisons et qui va elle aussi hériter de GenericAretes). Donc si j'ai bien compris cette deuxième solution est à écarter.
    En ce qui concerne la troisième solution, j'avoue sincèrement que je ne l'ai pas comprise et surtout que je ne sais pas le faire.
    indirection supplémentaire qui te permettra d'utiliser le double dispatch
    Si vous avez besoin de plus de codes ou indices qui pourraient me guider n'hésiter pas à me le demander.
    Encore merci à vous pour vos réponses rapides.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    Citation Envoyé par lodacom Voir le message
    Et malheureusement je vais avoir une autre classe (qui va s'appeler GenericLiaisons et qui va elle aussi hériter de GenericAretes). Donc si j'ai bien compris cette deuxième solution est à écarter.
    A moins d'utiliser le dynamic_cast et de prendre soin de vérifier que son résultat n'est pas null...

    Mais, de manière générale, c'est aussi "à éviter" (d'autant plus que les template s'accordent globalement assez mal avec la déclaration des fonctions virtuelles qui est nécessaire pour profiter du dynamic_cast )
    En ce qui concerne la troisième solution, j'avoue sincèrement que je ne l'ai pas comprise et surtout que je ne sais pas le faire.
    L'idée est de rajouter une classe ou une fonction qui permette de prendre en charge une partie spécifique de ton problème (c'est cela que l'on appelle une "indirection supplémentaire).

    au début, j'avais sans doute pensé plus à quelque chose proche du principe du visiteur qu'autre chose.

    Mais, à la réflexion, je me dis que l'idéal serait sans doute plutot de se baser sur un principe proche du patron de conception "décorateur".

    Tu aurais une classe permettant de récupérer un pointeur sur le type dérivé et qui te servirait pour ton argument
    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

  6. #6
    Membre confirmé
    Homme Profil pro
    PHP + JAVA
    Inscrit en
    Mars 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : PHP + JAVA

    Informations forums :
    Inscription : Mars 2009
    Messages : 65
    Par défaut Conversion non viable
    Alors voilà, j'ai fait d'après ce que j'avais compris
    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
     
    template <class G,class S,class A>
    GenericAretes<G,S,A>::GenericAretes(G* p_arete_dans,S* p_somm1,S* p_somm2){
        num++;
    	stringstream s;
        s << "A" << num;
    	nom_arete=s.str();
        arete_dans=p_arete_dans;
    	somm1=p_somm1;
    	somm2=p_somm2;
        somm1->setSommet_dans(p_arete_dans);
        somm2->setSommet_dans(p_arete_dans);
        IndirectionGeneric* ig=new IndirectionGeneric();
        somm1->addArete(ig->conversion(*this));
    }
    //nouveau code
    J'ai créé comme tu me l'a conseillé une classe qui récupère le pointeur de la classe dérivé et j'ai fait une fonction conversion mais ça ne lui plaît pas du tout.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    //indirectiondeneric.h
    class IndirectionGeneric{
    public:
        GenericAretes<GenericReseaux,GenericNoeuds,GenericLiens>* recup;
     
        IndirectionGeneric();
        GenericAretes<GenericReseaux,GenericNoeuds,GenericLiens>* conversion(GenericAretes<GenericReseaux,GenericNoeuds,GenericLiens>*);
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    //indirectiongeneric.cpp
    IndirectionGeneric::IndirectionGeneric(){}
     
    GenericAretes<GenericReseaux,GenericNoeuds,GenericLiens>* IndirectionGeneric::conversion(GenericAretes<GenericReseaux, GenericNoeuds, GenericLiens>* p_truc){
        recup=p_truc;
        return recup;
    }
    Il me dit que ma conversion n'est pas viable (ce qui peut se comprendre puisque dès que je rajouterai une classe je devrai surcharger ma fonction de conversion. Et aussi dès que j'enlève le "*" avant le this je reviens à mon erreur précédente..
    Voici l'erreur exacte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    GenericAretes.h:58:36: No viable conversion from 'GenericAretes<GenericReseaux, GenericNoeuds, GenericLiens>' to 'GenericAretes<GenericReseaux, GenericNoeuds, GenericLiens> *'
    Enlever tous les pointeurs ne serait-il pas une solution (en plus)? J'ai l'impression que je suis proche de la solution.
    Merci encore pour votre aide rapide.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    A vrai dire, je pensais en réalité à une classe proche de quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <typename Base, typename Derived>
    class Decorator : public Base{
        public:
           /* j'adore les typedefs :D */
           typedef Derived derived_type;
           derived_type * realType(){return real_;}
        protected:
           Decorator(derived_type * real )=real_(real){}
           ~Decorator(){}
        private:
            derived_type * real_;
    };
    qui serait utilisée (pour ta classe GenericLiens, si j'ai bien compris ) sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename A, typename B, typename C>
    class GenericLiens : public Decorator<GenericAretes<A, B, C>, GenericLiens>{
        public:
            GenericLiens(/*...*/):Decorator<GenericAretes<A, B, C>, GenericLiens>(this){}
        /* ... */
    };
    et dont tu te servirais dans ta classe GenericAretes sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <class G,class S,class A> // G = Decorator<Base,Derived> :D
    GenericAretes {
        public:
            typedef typename G::derived_type real_data_type;
            GenericAretes(G* p_arete_dans,S* p_somm1,S* p_somm2){
                arete_dans = p_arete_dans->realType();
            } 
        private:
            real_data_type * arete_dans;
    };
    Bon, ce code n'est absolument pas testé, mais l'idée de base est de cet ordre
    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: 2
    Dernier message: 07/10/2010, 19h05
  2. [AC-2007] Passage d'un objet en paramètre
    Par guit21 dans le forum VBA Access
    Réponses: 8
    Dernier message: 12/07/2010, 11h26
  3. [WD14] Passage d'un objet en paramètre à une fenêtre
    Par ritchi46 dans le forum WinDev
    Réponses: 21
    Dernier message: 04/05/2010, 09h35
  4. Retour d'objet générique / paramétré
    Par Jabbal'H dans le forum Langage
    Réponses: 4
    Dernier message: 03/04/2008, 15h31
  5. passage d'un objet en paramètre
    Par g30167 dans le forum C++
    Réponses: 2
    Dernier message: 14/12/2007, 23h25

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