Problème avec un pointeur passé en paramètre

Résolu
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 - 7 sept. 2007 à 14:39
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 - 27 sept. 2007 à 08:35
Bonjour à tou(te)s !
J'ai un petit problème avec un pointeur passé en paramètre...
Voici ce qui se passe:
J'ai une classe abstraite A, une classe fille AA et une troisième classe B.
Ma classe B a une méthode qui reçoit en paramètre un A*.
J'aimerais que la valeur du paramètre soit modifiée.  Or, quand je passe un AA*, ça ne fonctionne pas...
J'ai tenté de modifier la méthode en passant un A*&, mais lorsque je passe un AA*, il me dit que le compilo me dit que le type est incorrect, qu'il ne sait pas passer un AA*&, parce que le type est un A*&...
Quelqu'un peut m'aider ?
Merci d'avance !

22 réponses

luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 sept. 2007 à 18:01
Mais dans ton fichier, tu as obligatoirement une donnée qui précise le type de l'objet. A partir de cette donnée, ta classe B saura quel objet retourner. En général, on utilise des fonctions "clone" pour faire cela. Ca permet de faire tout cela de façon dynamique et de pas avoir besoin de recompiler le code pour  gérer un nouveau type de données. Lorsque tu charges tes classes qui dérivent de A (que ce soit par plugin ou directement dans le code), tu fournis a la classe B l'identifiant et un objet de la classe.

Plus concrètement, on associe un numéro a chaque classe. Lorsque tu créés une classe X (qui dérive de A),  tu envois à la classe B l'identificateur de ta classe X (un numéro unique) et un object de la classe X. Lorsque ta classe B lis le fichier, et qu'elle tombe sur un identificateur de classe, elle le lit, et regarde dans sa table regroupant tous les identificateurs et un objet associé:
La table peut avoir la définition suivante: std::map

Si l'identificateur est connu, on appelle la fonction "virtual A * clone() const" (virtuelle pure de A). Dans le cas de la classe X, la fonction est: virtual A* X::clone() const { return new X(*this); }
Il suit après un appel à la fonction virtuelle "readfromfile".

Donc en gros, ta fonction de lecture dans ta classe B a l'allure suivante:
A * B::readFile(ifstream &)
{
      si on rencontre un identificateur de classe, soit "k" cet identificateur.

      si on trouve cet identificateur ddans la table (ce qui est normalement le cas)
      {
           A * object = table[ k ]->clone();
           object->readfromfile(ifstream);

          return object;
      }
      else
     ....
}

Elle peut aussi avoir la définition suivante. C'est pareil, voir plus pratique:
bool B::readFile(ifstream &, A * &);

De cette facon, on utilise uniquement le polymorphisme, mais il faut nécessairement une phase, où on fournit la liste des classes que doit gérer ta classe B.

ta classe A doit posséder les fonctions suivants:
virtual A * clone() const = 0;
virtual void readFromFile(ifstream) = 0;

Quand tu utilises la fonction de lecture B::readFile(...), tu ne manipules que des pointeurs de type A*.

std::vector objects;
A * newObject = NULL;

while (B::instance()->readFile(ifstream, newObject))
     objects.push_back(A);

Bon j'espère que la longueur du post n'est pas au détriment de la compréhension :)
Donc en conclusion une méthode de ce type ne permet de gérer la lecture de n'importe quel type d'objet pourvu que ta classe soit connu de la classe B (le manager qui se charge de lire les objets), ce qui parait etre le minimum. L'avantage c'est que tout est dynamique.
3
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 15:08
C'est normal que ca plante, c'est illégal : tu as le droit de convertir un AA* en A* (base du polymorphisme quand même) mais pas un AA* en A*&. Pourquoi cela ? Imagine que dans ta fonction tu alloues au pointeur un objet de base (oublions l'abstraction ca change rien) :


void Test(A*&pA){pA=new A;return;}


Dans ce cas, si tu passes un AA* en appel de la fonction, tu vas te retrouver à essayer de convertir un A* en AA*... ce qui est pour le coup interdit.
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
7 sept. 2007 à 15:22
Merci juju12, mais alors, comment puis-je faire ?
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 16:50
TU PEUX PAS !
Ou alors surcharge ta fonction pour qu'elle accepte en argument un coup un A*&, un autre version un AA*&.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
7 sept. 2007 à 17:01
En fait, je dois faire hériter pas mal de classes de A, et j'aurais voulu utiliser le polymorphisme, parce que toutes mes classes filles doivent utiliser cette fonction memebre...
Il n'y a vraiment AUCUN moyen ?
J'avais pensé à l'identification dynamique des types avec typeinfo et bidouiller qqch avec ça, mais je trouve cela un rien fastidieux...
0
DeAtHCrAsH Messages postés 2670 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 6 février 2013
7 sept. 2007 à 17:15
A*& ????
Kesako.... Jamais vu o_O !
* = Pointeur et &=Reference.
C'est joli mais je doute de l'utilité de ce truc....

Shell
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 17:20
DeAtHCrAsH => moi non plus j'avais jamais vu
exar => bien sûr mais pourquoi as-tu absolument besoin de passer le pointeur par référence? C'est pas très propre de faire ca, après vu de l'extérieur on sait pas si le code a créé un nouvel objet, s'il a libéré correctement l'ancien etc...
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
7 sept. 2007 à 17:48
Si, ça existe.  En fait, à l'intérieur de ma fonction memebre, je dois modifier mon pointeur.  Je ne crée pas de nouvel objet.
J'ai tenté de surcharger l'opérateur d'affectation pour cela, d'abord en le déclarant virtuel pu dans la classe de base, puis simplement virtuel, mais il ne l'appelle jamais lorsque j'affecte ma nouvelle valeur au paramètre...  J'ai fait une trace d'exécution, et bizzarement, il n'appelle jamais l'opérateur surchargé...
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 18:28
Mais POURQUOI tu veux modifier ton pointeur?
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
7 sept. 2007 à 18:47
Ben voilà, en fait, ma classe B représente un fichier.  La méthode appellée (qui a pour paramètre A*) va lire dans le fichier et récupère les données.  La classe A est la classe de base, abstraite.  AA est une des classes filles.  A possède une méthode virtuelle pure qui renvoie un A*.  Dans la méthode de B, j'essaie de faire une affectation sur mon paramètre, en appelant la méthode de AA*.
En bref, tu as un truc du style:
class A{
    //membres privés, constructeurs, destructeur, etc...
   virtual A* readfile(fstream&)=0;
}

class AA: public A{
   //idem que A
   A* readfile(stream&);
};

Implémentation:

A* AA::readfile(fstream& arg){
   //récupération des données dans le stream
   return new AA(<mes données>);
}

Dans B:
class B{
private:
   fstream _file;
   //...
   void get(A*);
};

Implémentation:
void B::get(A* arg){
   arg=arg->readfile(_file);
}

Ainsi, j'espérais pouvoir récupérer mes données pour n'importe quel descendant de A...  Mais ça ne fonctionne pas...  J'arrive à récupérer les données dans le fichier, mais mon pointeur n'est pas modifié...
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
7 sept. 2007 à 19:14
Un exemple de référence sur pointeur, pour vous prouver que ça existe:
http://www.codeproject.com/cpp/PtrToPtr.asp
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 20:37
Je vois ce que tu veux faire; j'ai pas de solution autre que de surcharger ta fonction, une pour un argument A*& et l'autre pour un argument AA*&.
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
7 sept. 2007 à 20:54
juju12 => donc passer par l'identification dynamique des types...  Mais ce n'est plus de la POO, ça...  Si j'ajoute un type, je dois modifier.  Plus de polymorphisme...
Vraiment personne pour une solution "propre" ?
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
7 sept. 2007 à 22:40
Je viens de tomber sur ce post. Je comprend pas tout a fait le but de cette fonction:
class AA: public A{
   //idem que A
   A* readfile(stream&);
};

La fonction readfile, retourne quoi ?

Autre question dans la classe B, cette définition de get te convient pas ?
A* B::get(A*);

Je comprend pas bien ce que tu veux faire mais j'imagine que tu veux récupérer à partir du fichier, des objets dérivant de A ?
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 23:01
exar => le seul truc que je vois est peut-être ca mais c'est pas très joli:
A* B::get(A*pA){return pA->read();}

et dans le code avec un AA*:
AA*pAA;
pAA=dynamic_cast(B.get(pAA));

Mais il faut que tu saches à l'avance le type réel de l'objet référencé par le pointeur.
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
7 sept. 2007 à 23:04
Au fait l'identification dynamique des types y en a partout en POO:
imagine t'as une méthode virtuelle Func() de AA*, si tu fais:
A* pA=new AA;
pA->Func();

le code doit identifier en dynamique le type de l'objet pointé par pA, bien qu'on en ait pas l'impression au vu du code.
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
8 sept. 2007 à 06:25
luhtor: oui, c'est exactement ce que je veux faire.  Le principe est le suivant: B::get affecte au paramètre la valeur chargée dans le fstream.  Et chaque classe descendant de A récupère elle-même ses données dans le fichier et les renvoie.  Donc, dans l'implémentation de B::get(A* arg), j'ai un truc du style arg=arg->readfile(arg)...

juju12: je parlais de l'identification de type avec typeinfo.  Je vais
tenter les choses ainsi, je dirai si ça fonctionne ainsi...
0
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 1
8 sept. 2007 à 06:34
Mais en fait, non, je ne vais pas essayer, parce que sinon, ma classe abstraite n'a plus de raison d'être, ce qui ne m'arrange pas...  J'aimerais vraiment une méthode polymorphe...
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
8 sept. 2007 à 18:04
Juste un détail, cet identificateur unique, ca peut etre aussi le nom de classe :) ce qui est assez pratique.
Et donc je pense que ca répond a ce que tu voulais, c'est à dire une méthode entièrement basée sur le polymorphisme.
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
8 sept. 2007 à 20:05
Un détail tout de même : comme ta fonction retourne un pointeur sur classe de base tu ne pourras pas utiliser les méthodes spécifiques de la classe dérivée (hors les virtuelles héritées de la classe de base s'entend); si tu n'en a pas c'est pas un problème, dans le cas contraire faudra à nouveau un dynamic_cast.
0
Rejoignez-nous