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 :

reference sur pointeur


Sujet :

C++

  1. #1
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut reference sur pointeur
    Bonjour,

    Je cherche, dans une fonction, à modifier la valeur d'un pointeur qui est passé en paramètre.

    Je veux bien modifier la valeur du pointeur (l'adresse sur laquelle il pointe) et non pas les données pointées (sinon, c'est facile...)

    J'ai donc essayé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool createObject(CoreObject*& pObject)
    Mais le compilo n'a pas l'air d'aimer ça... (je n'ai plus les messages d'erreur sous la main)

    Existe-t-il une solution autre que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool createObject(CoreObject** pObject)
    Merci !

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 16
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Points : 65
    Points
    65
    Par défaut
    Salut,

    il n'y a pas de problèmes.

    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
    #include <iostream>
    #include <vector>
    #include <cmath>
     
    using namespace std;
     
    int a (int *&b)
    {
        b=NULL;
    }
     
    int main(){
        int d;
        int *c = &d;
        a(c);
        cout << c << endl;
        return 0;
    }

  3. #3
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ah ! Oui !

    Je m'a trompé dans la description...

    J'ai cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool createObject(CoreObject*& pObject)
    Et par exemple, la classe CoreNode derive de CoreObject. Le code suivant ne passe pas (probleme de conversion)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CoreNode* pNode = NULL;
    createObject(pNode)
    Pour cause de problemes de types.... pourtant la conversion est valide, non ?

    Pour info, derriere cette fonction, il y a un mecanisme qui me garantit que l'on ne fera pas pointer un CoreNode* vers un CoreObject, mais seulement vers un CoreNode.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 16
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Points : 65
    Points
    65
    Par défaut
    Il vaudrait mieux utiliser des templates si tu veux qu'une fonction ait un comportement différent selon le type de l'argument utilisé.

    Ou alors faire deux fonctions, une qui prend un CoreObject*, une autre qui prend un CoreNode*.

    Sans plus de détails sur les fonctions, il est difficile de voir ce qui cloche ou si on peut faire un cast assez barbare.

  5. #5
    Membre confirmé
    Inscrit en
    Août 2004
    Messages
    556
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 556
    Points : 588
    Points
    588
    Par défaut
    Comme le décrit Dreambeliever, on n'initialise pas un objet par son ancêtre. On l'initialiser au bon type, et ensuite on l'upcast.

  6. #6
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Effectivement, je viens de comprendre mon erreur...

    Du coup, en faisant ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <class T> bool createObject(T*& pObject)
    Effectivement, ça marche...

    Comme le décrit Dreambeliever, on n'initialise pas un objet par son ancêtre. On l'initialiser au bon type, et ensuite on l'upcast.
    Tout à fait d'accord... mais c'est un cas un peu particulier : des objets (dont on ne connait pas le type à l'avance) sont chargés depuis du XML à l'aide de plugins...

    En gros, dans le code, on ne connait pas le type de ce qu'on manipule... et cette fonction permet d'essayer de creer un objet d'un type donné depuis un fichier XML :

    => si tout se passe bien (XML valide, plugin trouvé, chargé...) on recupere un pointeur valide
    => en cas de soucis, on recupere un pointeur NULL

    En gros cette fonction s'occupe de tout : chargement, decodage, lancement du plugin et "cast" de l'objet en l'interface voulue (si possible)

    Et tout ça bien sûr, "extensible" : sans modifier le soft "central" on peut ajouter de nouveaux plugins capables de gerer de nouveau types d'objets : les charger, les créer, les ajouter dans le graphe de noeuds, faire des traitements dessus... sans qu'on ne connaisse quoique ce soit sur l'objet à l'avance (à par son type de base : CoreObject)

  7. #7
    Membre régulier Avatar de cynique
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Points : 72
    Points
    72
    Par défaut
    Citation Envoyé par buzzkaido Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool createObject(CoreObject*& pObject)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CoreNode* pNode = NULL;
    createObject(pNode)
    Pour cause de problemes de types.... pourtant la conversion est valide, non ?
    Non. Regarde ces declarations:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      void createObject1( CoreObject *pObject );
     
      void createObject2( CoreObject *&rpObject );
    Dans le premier cas, pObject est un pointeur. Il cible un CoreObject ou un objet d'une classe dérivée de CoreObject.

    Dans le deuxième cas, rpObject est une réference. Elle ne cible que "un pointeur sur un CoreObject".

    Un pointeur sur un CoreNode n'est pas un pointer sur un CoreObject, et la réference rpObject ne peut pas cibler un CoreNode *.

  8. #8
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Exact, mais je pensais que le compilo était capable de déduire la conversion, vu que les types concernés héritent l'un de l'autre.

    Merci !

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le problème, c'est que ça permettrait de faire ceci sans warning:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    bool createObject(Base *&rpObj)
    {
    	rpObj = new DerivA;
    	return true;
    }
     
    int main(void)
    {
    	DerivB *pObj;
    	createObject(pObj);
    }
    C'est pourquoi, même si X* est implicitement convertible en Y*, X*& n'est pas implicitement convertible en Y*&.
    Il en est de même pour X** et Y**, d'ailleurs.
    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.

  10. #10
    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
    Par défaut
    Bonjour,
    Peut-être peux-tu mettre en oeuvre le pattern factory et utiliser le retour-co-variant.

  11. #11
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    En fait, ma solution est inspirée de ce pattern. Mais :

    pas de retours co-variants car :
    - utile que si le compilo connait le type exact que l'on manipule à la compilation (sinon il ne peut contrôler les contraintes de co-variance)
    - justement, je ne connais presque rien à la compilation

    type de retour template (pour les opérations de création) permettant de "demander" de créer un objet de tel type depuis un jeu de données (XML ou autre) :
    - l'objet construit est du type "concret" de l'objet stocké dans le XML (le "vrai" type écrit dans le XML)
    - si l'objet peut être retourné (casté en T*) il est retourné
    - sinon il est détruit, et NULL est retourné

    Ainsi :

    - on peut demander la création d'un objet "Base*" a partir de données dans XML du type "Fils*" : un nouveau objet Fils sera créé puis retourné sous la forme d'un "Base*"

    - dans le code de l'appli, je ne manipule que des types que je connais (en général, la classe mère), si des plugins sont chargés avec des objets de type nouveaux (non connus de moi) le code fonctionne quand même

    - dans le code des factory qui sont incluses dans les plugins, le système de template permet de n'avoir a implémenter que des fonctions du style :

    (exemple pour la factory associée à un CoreNodeGroup, qui derive de CoerNode, qui derive de CoreObject)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Menu* createMenu(CoreNodeGroup* pGroup)
    Avec bien comme parametre "CoreNodeGroup* pGroup" et non pas "CoreObject* pObject".

    Ce qui simplifie grandement le travail des développeurs qui implémentent les plugins : plus besoins de se soucier du type, de down-caster ou quoique ce soit, toutes les signatures de méthodes sont adaptées.

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

Discussions similaires

  1. Reference sur la destination d'un pointeur
    Par Kiwii dans le forum Débuter
    Réponses: 6
    Dernier message: 10/12/2010, 19h26
  2. pointeur sur pointeur
    Par gaut dans le forum C
    Réponses: 3
    Dernier message: 01/11/2005, 21h30
  3. Pb reference sur une globale inutilisée (VC6)
    Par symmenthical dans le forum MFC
    Réponses: 1
    Dernier message: 11/05/2005, 21h35
  4. Probleme heritage : References sur la table parente
    Par Belgar dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 03/05/2005, 22h11
  5. reference sur un objet
    Par romeo9423 dans le forum C++
    Réponses: 5
    Dernier message: 16/02/2005, 21h53

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