Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1819 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  comment dupliquer une liste de pointers ? (les objets pointés aussi).

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

comment dupliquer une liste de pointers ? (les objets pointés aussi).

n°283879
karim63
Posté le 10-01-2003 à 22:14:26  profilanswer
 

comment dupliquer une liste de pointers ? (les objets pointés aussi).
 
pour stocker des elements dans une liste chainée generique avec templates (g fait l'implementation) afin de pouvoir stocker des classes et aussi des classes dérivées du type de base, j'utilise une liste chainée dont les noeuds contienent un champ avec la valeur du pointeur.
 
donc pour rentrer un element je dois faire l.add(new machin(bidule,truc))
Là je peux conserver le type reels de objets contrairement au cas ou j'utilise un attribut du type machin dans mon noeud.
Et donc je vois pas comment faire pour dupliquer la liste. :heink:
J'ai tenté des trucs avec typeof etc, mais le compilo (g++) subit une erreur interne, et il veut que j'envoit un mail [:ddr555]
 
Mon but etait de faire une liste generique qu'il soit possible de dupliquer.


Message édité par karim63 le 15-01-2003 à 20:35:27
mood
Publicité
Posté le 10-01-2003 à 22:14:26  profilanswer
 

n°283885
Taz
bisounours-codeur
Posté le 10-01-2003 à 22:20:37  profilanswer
 

muni tes objets d'une méthode clone()

Code :
  1. Foo* Foo::clone() const
  2. {
  3.   return new Foo(*this);
  4. }

n°283887
LeGreg
Posté le 10-01-2003 à 22:22:20  profilanswer
 

Code :
  1. class A {
  2.   virtual A* Clone() const {return new A(*this);};
  3. }
  4. class B : public A {
  5.   virtual A* Clone() const {return new B(*this);}
  6. }


 
C'est ca que tu veux ?
 
LeGreg
edit: grille comme d'hab


Message édité par LeGreg le 10-01-2003 à 22:23:12

---------------
voxel terrain render engine | animation mentor
n°283894
karim63
Posté le 10-01-2003 à 22:37:20  profilanswer
 

mmm effectivement c ça qu'il me faut. J'avais vu que y avait ça en java mais j'ai pas percuté merci  :) .
Sinon je mettrais bien le code histoire de ce marrer [:ddr555]

n°283900
karim63
Posté le 10-01-2003 à 22:43:13  profilanswer
 

sinon seul prob, j'aurais voulu pouvoir l'utiliser sur des types standart.
l.add(new int (i) );
 
comment rajouter la methode clone sur ce type ?
Je vois en specialisant le patron, mais y pas d'ot moyens ?

n°283908
Taz
bisounours-codeur
Posté le 10-01-2003 à 22:57:42  profilanswer
 

non. tiens une interrogation. est ce que c'est possible de spécialiser un template pour les types de bases, spécialisation de tempalte qui ferait appel à une unique classe template servant de wrapper+clone aux types de bases

n°283918
Taz
bisounours-codeur
Posté le 10-01-2003 à 23:14:34  profilanswer
 

Code :
  1. template<class T>
  2. class Container
  3. {
  4. public:
  5.   static void check_preconditions()
  6.   {
  7.     static T* ptr=NULL;
  8.     if(ptr==NULL)
  9.       {
  10. const T tmp;
  11. ptr=tmp.clone();
  12. delete ptr;
  13.       }
  14.   }
  15.    
  16. public:
  17.   Container()
  18.   {
  19.     check_preconditions();
  20.   }
  21. };
  22. template<class T>
  23. class BaseTypeWrapper
  24. {
  25.   T* item;
  26. public:
  27.  
  28.   T* clone() const
  29.   {
  30.     return new T(*item);
  31.   }
  32. };
  33. template<class BaseType> class Container< BaseTypeWrapper<BaseType> >
  34. {
  35. };
  36. template<> class Container<int> : public Container< BaseTypeWrapper<int> >
  37. {
  38. };
  39.  
  40. // etc et à compléter evidemment


 
ça me parait devoir marcher...
 
le type template doit etre muni d'une méthode T* clone() const. et pour obtenir ce const, on doit instancier un objet const: on fait donc appel a son constructeur par défaut. Donc T doit aussi posséder un constructeur par défaut.
 
edit: il y a sans doute pas mal de modification à apporter, mais c'est une piste interessante. mais en y réflechissant, disposer d'un conteneur pour manipuler des objets polymorphes qui s'adaptent aussi aux types de bases n'a pas vraiment de sens. Il faut chercher dans la spécialisation de template, certes, mais je pense qu'il faut surtout designer un conteneur dédié à ce genre de travail. Mais l'exercice de style est interessant et a retenir. Ici la synthaxe est sans doute mauvaise, les noms des paramètres templates mal choisis, des pointeurs là alors qu'il n'en faudrait pas, bref c'est la jungle. Me jetez pas la pierre, j'ai essayez de répondre à la question: on peut pas faire du tout en un. Le problème m'interesse mais j'ai pas le temps de le traiter, je vais pas non plus faire tout le boulot. et il me reste 23épisodes de 24H chrono a regardé


Message édité par Taz le 11-01-2003 à 01:47:10
n°283924
karim63
Posté le 10-01-2003 à 23:50:08  profilanswer
 

Je peux pas te répondre du tout.
 
Je met le code pour avoir des critiques constructives vu que y en a qui sont callés.
 

Code :
  1. template <class T> class Pnode
  2. {
  3.  
  4. private:
  5.   T info;
  6.   Pnode<T>* next;
  7.   Pnode<T>* pred;
  8. public:
  9.   Pnode(T,Pnode<T>*,Pnode<T>*);
  10.   Pnode(const Pnode<T>&);
  11.   ~Pnode(); 
  12.   Pnode<T>* getnext();
  13.   Pnode<T>* getpred();
  14.   T getinfo();
  15.   void setnext(Pnode<T>*);
  16.   void setpred(Pnode<T>*);
  17.   void setinfo(T);
  18.  
  19. };
  20. template<class T> class Plist
  21. {
  22. private:
  23.   int size;
  24.   Pnode<T>* first;
  25.   Pnode<T>* last;
  26.   Pnode<T>* getnode(int)const;
  27. public:
  28.   Plist();
  29.   Plist(const Plist&);
  30. ~Plist(); 
  31.   void operator=(const Plist&);
  32.   bool empty();
  33.   int getsize()const;
  34.   Plist<T>& add(T);
  35.   Plist<T>& adde(T);
  36.   T get(int)const ;
  37.   Plist<T>& del(int);
  38.   void affiche(ostream&);
  39. };
  40. template<class T> ostream& operator<<(ostream&,Plist<T>&);


 

Code :
  1. #include <iostream>
  2. #include <string>
  3. #include "Plist2.h"
  4. class Kexception
  5. {
  6. public:
  7.   Kexception(string message)
  8.   {
  9.     cout << message;
  10.   };
  11. }; 
  12. template<class T> Pnode<T>::Pnode(T Pelement,Pnode<T>* p,Pnode<T>* n)
  13. {
  14.   info=Pelement;
  15.   next=n;
  16.   pred=p;
  17. };
  18.  
  19. template<class T> Pnode<T>:: ~Pnode()
  20. {
  21.   delete info;
  22. };
  23.  
  24. template<class T> Pnode<T>::Pnode(const Pnode<T> &n)
  25. {
  26.   info=n.info->clone();
  27.   next=NULL;
  28.   pred=NULL;
  29. };
  30. template<class T> Pnode<T>*  Pnode<T>::getnext()
  31.   {
  32.     return next;
  33.   };
  34. template<class T> Pnode<T>*  Pnode<T>::getpred()
  35.   {
  36.     return pred;
  37.   };
  38.  
  39. template<class T> T  Pnode<T>::getinfo()
  40.   {
  41.     return info;
  42.   };
  43. template<class T> void  Pnode<T>::setinfo(T Pelement)
  44.   {
  45.     delete info;
  46.     info=Pelement;
  47.   };
  48.  
  49. template<class T> void  Pnode<T>::setpred(Pnode<T>* p)
  50.   {
  51.     pred=p;
  52.   };
  53.  
  54. template<class T>  void  Pnode<T>::setnext(Pnode<T>* n)
  55.   {
  56.     next=n;
  57.   };
  58. template<class T> Plist<T>::Plist()
  59. {
  60.   first=NULL;
  61.   last=NULL;
  62.   size=0;
  63. };
  64. template<class T> Plist<T>::Plist(const Plist &l)
  65. {
  66.   first=NULL;
  67.   last=NULL;
  68.   size=0;
  69.   if (!(l.getsize()==0))
  70.     {
  71.       Pnode<T>* n=l.getnode(1);
  72.       for(int i=1;i<=l.getsize();i++)
  73. {
  74.   adde(n->getinfo()->clone());
  75.   n=n->getnext();
  76. };
  77.     };
  78.  
  79. };
  80. template<class T> void Plist<T>::operator=(const Plist &l)
  81. {
  82.   if (!(&l==this))
  83.     {
  84.       while (!(size==0))
  85.       {
  86.       del(1);
  87.       };
  88.       if (!(l.getsize()==0))
  89. {
  90.   Pnode<T>* n=l.getnode(1);
  91.   for(int i=1;i<=l.getsize();i++)
  92.     {
  93.       adde(n->getinfo()->clone());
  94.       n=n->getnext();
  95.     };
  96. };
  97.     };
  98. };
  99. template<class T> Plist<T>::~Plist()
  100.   {
  101.     while (!(size==0))
  102.       {
  103.      del(1);
  104.       };
  105.   };
  106. template<class T>  bool Plist<T>::empty()
  107. {
  108.     return size==0;
  109. };
  110. template<class T>  int Plist<T>::getsize()const
  111. {
  112.     return size;
  113. };
  114. template<class T>  Plist<T>& Plist<T>::add(T Pobj)
  115. {
  116.   Pnode<T>* n=new Pnode<T>(Pobj,NULL,first);
  117.   if (!(first==NULL)) {first->setpred(n);};
  118.   first=n;
  119.   if (size==0) {last=n;};
  120.   ++size;
  121.   return *this;
  122. };
  123. template<class T>  Plist<T>& Plist<T>::adde(T Pobj)
  124. {
  125.   Pnode<T>* n=new Pnode<T>(Pobj,last,NULL);
  126.   if (!(last==NULL)) {last->setnext(n);};
  127.   last=n;
  128.   if (size==0) {first=n;};
  129.   ++size;
  130.   return *this;
  131. };
  132. template<class T>  Pnode<T>* Plist<T>::getnode(int j)const
  133. {     
  134.   if (size==0) throw Kexception("get on empty list" );
  135.   if ((j<=0) || (j>size)) throw Kexception("get out of bound of list" );
  136.   Pnode<T>* n;
  137.   if (j<=((size / 2)+1))
  138.     {
  139.       n=first;
  140.       for(int i=1;i<j;i++)
  141. {
  142.   n=n->getnext();
  143. };
  144.     }
  145.   else
  146.     {
  147.       n=last;
  148.       for(int i=size;i>j;i--)
  149. {
  150.   n=n->getpred();
  151. };
  152.     };
  153.   return n;
  154. };
  155. template<class T>  T Plist<T>::get(int j)const
  156. {
  157.   return this->getnode(j)->getinfo();
  158. };
  159. template<class T>  Plist<T>& Plist<T>::del(int j)
  160. {
  161.   if (size==0) throw Kexception("del on empty list" );
  162.   if ((j<=0) || (j>size)) throw Kexception("del out of bound of list" );
  163.   Pnode<T>* neud;
  164.   Pnode<T>* pred;
  165.   Pnode<T>* next;
  166.   neud=this->getnode(j);
  167.   pred=neud->getpred();
  168.   next=neud->getnext();
  169.    
  170.   if (first==neud)
  171.     {
  172.       first=next;
  173.     }
  174.   else
  175.     {
  176.       pred->setnext(next);
  177.     };
  178.   if (last==neud)
  179.     {
  180.       last=pred;
  181.     }
  182.   else
  183.     {
  184.       next->setpred(pred);
  185.     };
  186.   delete neud;
  187.   --size;
  188.   return *this;
  189. };
  190. template<class T>  void Plist<T>::affiche(ostream& os)
  191. {
  192.   Pnode<T>* f;
  193.   Pnode<T>* l;
  194.   f=first;
  195.   l=last;
  196.   for(int i=1;i<=size;i++)
  197.   {
  198.     os << *f->getinfo() << " ";
  199.     f=f->getnext();
  200.   };
  201. };
  202. template<class T> ostream& operator<<(ostream& os,Plist<T>& l)
  203. {
  204.   l.affiche(os);
  205.   return os;
  206. };
  207. class entier
  208. {
  209. public:
  210.   int val;
  211.   entier(int x=0){val=x;++nbe;/*cout << nbe<<endl;*/};
  212.   entier(const entier &e){val=e.val;++nbe;};
  213.   ~entier(){--nbe;/*cout << nbe<<endl;*/};
  214.   virtual entier* clone()
  215.   {
  216.     return new entier(*this);
  217.   };
  218.   static int nbe;
  219.   virtual void affiche(ostream& os)
  220.   {
  221.     os<<val;
  222.   };
  223. };
  224. int entier::nbe=0;
  225. class entier2:public entier
  226. {
  227. public:
  228.   int val2;
  229.   entier2(int x=0,int y=0):entier(x){val2=y;};
  230.   entier2(const entier2 &e){*this=e;};
  231.   virtual entier2* clone()
  232.   {
  233.     return new entier2(*this);
  234.   };
  235.   virtual void affiche(ostream& os)
  236.   {
  237.     os<<"(" <<val<<","<<val2<<" )";
  238.   };
  239.  
  240. };
  241. ostream& operator<<(ostream& os,entier &e)
  242. {
  243.   e.affiche(os);
  244.   return os;
  245. };
  246. main()
  247. {
  248.   Plist<entier*> l;
  249.   cout <<l<<endl;
  250.   for(int i=1;i<=10;i++)
  251.     {
  252.       l.add(new entier2(3*i,i) );
  253.     };
  254.   l.add(new entier(55));
  255.   cout <<l<<endl;
  256.   Plist<entier*> m;
  257.   m.add(new entier2(5,98));
  258.   m=l;
  259.   cout <<m<<endl;
  260. }


Message édité par karim63 le 10-01-2003 à 23:52:40
n°283927
Taz
bisounours-codeur
Posté le 11-01-2003 à 00:04:34  profilanswer
 

ca fait un peu beaucoup à lire:
 
petites remarques:  
 
 
- essaye de plus utiliser les références constantes dans tes paramètres (comme pour setinfo)
 
- si unefonction membre de modifie pas l'objet, mets l'attribut const (getinfo, empty)
 
- void operator=(const Plist&). si tu fais ça tu empeches l1=l2=l3. peut etre est-ce volontaire. sinon tu fais  

Code :
  1. const Plist & operator=(const Plist&)
  2. {
  3.   return *this;
  4. }


 
- utilise des types unsigned pour tes longueurs (je suis un chieur)
 
- ta methode affiche, bof, les ostream n'ont rien a faire avec ta classe (c'est une surspécification, dans la vraie vie, personne n'utilisera Plist.affiche(cout), on ne demande pas au structure de données de faire des GUI). la méthode consacrée, c'est string print() const, qui renvoie une chaine, représentation de l'objet
 
- vas y avec les inline
 
- construits tes membres

Code :
  1. class Foo
  2. {
  3.   Bar b;
  4.   std::vector<int> v;
  5. public:
  6.   Foo(const Bar &a_b) : b(a_b), v(10, 69)
  7.   { // des trucs
  8.    }
  9. };


 
- !(a==b)) <=> (a!=b)  !!!!!!!!!!!!!!!!!
 
- je crois pas avoir vu de using namespace std;
 
- initialise(sens large) tes varaibles au plus pres de leur déclaration

Code :
  1. // appel constructeur, puis operator=
  2. Pnode<T>* f;
  3. Pnode<T>* l;
  4. f=first;
  5. l=last;
  6. // il vaut mieux, seulement constructeur
  7. Pnode<T>* f(first);
  8. Pnode<T>* l(last);


 
- et le type de retour de main doit etre int (pas la peine de spécifier un return 0;)
 
- dans tes déclarations de classe: saute des lignes et evite de mixer déclaration de variables et déclaration de fonctions membres
 
- etc


Message édité par Taz le 11-01-2003 à 00:20:15
n°283928
karim63
Posté le 11-01-2003 à 00:17:15  profilanswer
 

-references constante:
hem vu que ce que je passe en param est un pointeur c pas tres utile de metre un const. Ok pour le passage par ref, mais vu que c'est un pointeur c même pas sur que le compilateur accepte.
 
-si unefonction membre de modifie pas l'objet, mets l'attribut const (getinfo, empty)
 
En fin de fonction c ça ?
 
-void operator=(const Plist&). si tu fais ça tu empeches l1=l2=l3. peut etre est-ce volontaire.
 
vaguement volontaire, je voyais pas l'interet, mais pkoi pas, je vais le rajouter.
 
- utilise des types unsigned pour tes longueurs (je suis un chieur)
 
[:ddr555]
 
- vas y avec les inline
 
J'ai commencé tout en inline [:ddr555] et j'ai mis dans un point h apres pour me forcer a la faire.
 
- construits tes membres
 
 :??: que veux tu dire par là ?
 
- (!(a==b)) <=> (a!=b)
 
exact je trouvais ça tout moche aussi .
 
- je crois pas avoir vu de using namespace std;
 
C'est quoi ?
 
-// il vaut mieux

Code :
  1. Pnode<T>* f(first);


tu veux dire:
 
Pnode<T>* f=first;
 
?

mood
Publicité
Posté le 11-01-2003 à 00:17:15  profilanswer
 

n°283931
Taz
bisounours-codeur
Posté le 11-01-2003 à 00:24:52  profilanswer
 

je crois que tu as lu un peu vite ma réposne précédente
 
mais remarques vise pas un bout de code particulier, mais l'ensemble. considères en une et regarde l'ensemble de ton code...
 
 
les namespace... il est ard: rajoute ça "using namespace std;" juste apres tes #include
 

Citation :


Code :
  1. Pnode<T>* f(first);


tu veux dire:
 
Pnode<T>* f=first;

c'est strictement équivalent, personnellement je préfère la premiere ecriture (bien entendu ici, le = n'a donc rien avoir avec operator=)

n°283939
karim63
Posté le 11-01-2003 à 00:37:50  profilanswer
 

Citation :

les namespace... il est ard: rajoute ça "using namespace std;" juste apres tes #include


 
je ne sais pas ce que c'est, ça sert a quoi ?

n°283981
nraynaud
lol
Posté le 11-01-2003 à 05:47:33  profilanswer
 

++Taz a écrit :

muni tes objets d'une méthode clone()

Code :
  1. Foo* Foo::clone() const
  2. {
  3.   return new Foo(*this);
  4. }




 
J'ai pas lu tout le topic, mais je me pose une question :
si je veux que ma liste soit sur des références, ou des pointeurs, je fait comment pour ajouter clone() au type (MaClasse &) ou (MaClasse *) ??

n°283982
nraynaud
lol
Posté le 11-01-2003 à 06:01:31  profilanswer
 

karim63 a écrit :


Code :
  1. #include <iostream>
  2. #include <string>
  3. #include "Plist2.h"
  4. template<class T> Pnode<T>::Pnode(const Pnode<T> &n)
  5. {
  6.   info=n.info->clone();
  7.   next=NULL;
  8.   pred=NULL;
  9. };




 
Rahaaaaa putaint de ta race, je passe ma vie à t'expliquer la différence entre initialisation et instanciation, et tu écris des merdes pareilles ????
 
C'est un putain de constructeur par copie, tu n'affectes pas les variables d'instance dans un constructeur tu les initialises (avec des putains de ":", deux point en français, colon in english, jamais avec "=", égal en français, equal in english)  :

Code :
  1. template<class T> Pnode<T>::Pnode(const Pnode<T> &n) : info(n.info), pred(NULL), next(NULL=){/* ce putain de code est vide*/}


Fait-moi plaisir, imprime un truc dans ta vie : la différence entre initialisation (la variable ne contenait aucune valeur significative avant) et affectation (la variable change de valeur).


Message édité par nraynaud le 11-01-2003 à 06:03:28
n°283985
Taz
bisounours-codeur
Posté le 11-01-2003 à 07:40:11  profilanswer
 

nraynaud a écrit :


 
J'ai pas lu tout le topic, mais je me pose une question :
si je veux que ma liste soit sur des références, ou des pointeurs, je fait comment pour ajouter clone() au type (MaClasse &) ou (MaClasse *) ??
 

ben comme je le propose, il faut introduire une double spécialisation de template par l'intermédiaire d'une classe wrapper&clone. le problème c'est surtout la sémantique: je ne vois pas trop l'interet d'avoir une fonction membre clone a part pour le polymorphisme qui se fait grace aux pointeurs en C++

n°284083
karim63
Posté le 11-01-2003 à 14:02:54  profilanswer
 

Citation :

Fait-moi plaisir, imprime un truc dans ta vie : la différence entre initialisation (la variable ne contenait aucune valeur significative avant) et affectation (la variable change de valeur).


 
hé connard tu vas parler sur un autre ton ?? :fou:  
Ce que je comprends et pas avec tes explications(y en a pas), c'est que si j'affecte a un attribut non instanticé un objet avec = , si il est pas initiliasié ça peut merder lors du vidage de l'objet censé ecrasé.
Soit plus clair dans tes explications. Il suffit pas de dire ce qu'il faut faire, il faut aussi dire pourquoi sinon ça sert a rien.

n°284105
nraynaud
lol
Posté le 11-01-2003 à 14:43:34  profilanswer
 

karim63 a écrit :

Citation :

Fait-moi plaisir, imprime un truc dans ta vie : la différence entre initialisation (la variable ne contenait aucune valeur significative avant) et affectation (la variable change de valeur).


 
hé connard tu vas parler sur un autre ton ?? :fou:  
Ce que je comprends et pas avec tes explications(y en a pas), c'est que si j'affecte a un attribut non instanticé un objet avec = , si il est pas initiliasié ça peut merder lors du vidage de l'objet censé ecrasé.
Soit plus clair dans tes explications. Il suffit pas de dire ce qu'il faut faire, il faut aussi dire pourquoi sinon ça sert a rien.


http://forum.hardware.fr/forum2.ph [...] t=#t272543
ho bah t'as raison, c'est une choucroute volante, j'ai cru que c'était une explication. A la page précédente, j'avais déjà fait la remarque (rapidement).

n°284110
nraynaud
lol
Posté le 11-01-2003 à 14:52:43  profilanswer
 

++Taz a écrit :


 
- void operator=(const Plist&). si tu fais ça tu empeches l1=l2=l3. peut etre est-ce volontaire. sinon tu fais  

Code :
  1. const Plist & operator=(const Plist&)
  2. {
  3.   return *this;
  4. }




 
C'est pas plutôt  

Code :
  1. const Plist & operator=(const Plist& other)
  2. {
  3.   return other;
  4. }


 

Code :
  1. int i = 10, j = 11, k;
  2. k = (i = j) //vaut 11 dans ma tête

n°284116
Taz
bisounours-codeur
Posté le 11-01-2003 à 15:15:17  profilanswer
 

ben c'est à peu pres la meme chose, a moins que ta sémantique de operator= soit differente de celle communément utilisée

n°284122
nraynaud
lol
Posté le 11-01-2003 à 15:26:50  profilanswer
 

++Taz a écrit :

ben c'est à peu pres la meme chose, a moins que ta sémantique de operator= soit differente de celle communément utilisée


 
C'est pas la mienne mais la tienne ... (si c'est vrai, nananère)

n°284311
galett
Miam Miam des galettes !
Posté le 11-01-2003 à 21:07:58  profilanswer
 

*s'imagine une choucroute qui vole*...beuurkkk  :lol:  
*se demande si la choucroute garde sa cohésion lorsqu'elle dépasse la vitesse du son*... :pt1cable:


---------------
mon NAS/HTPC Q11 H55N-USB3, Core i3 http://forum.hardware.fr/hfr/Hardw [...] m#t7599404
n°284319
lorill
Posté le 11-01-2003 à 21:24:38  profilanswer
 

Galett a écrit :

*s'imagine une choucroute qui vole*...beuurkkk  :lol:  
*se demande si la choucroute garde sa cohésion lorsqu'elle dépasse la vitesse du son*... :pt1cable:  


http://kadreg.free.fr/perso/moules [...] olante.jpg

n°284492
Musaran
Cerveaulté
Posté le 12-01-2003 à 04:45:47  profilanswer
 

nraynaud a écrit :

C'est pas plutôt

Code :
  1. int i = 10, j = 11, k;
  2. k = (i = j) //vaut 11 dans ma tête


Pour un type intégré, k reçoit la valeur de i après affectation (plus précisément, la valeur de j convertie dans le type de i).
Donc, si on veut être cohérent, on doit renvoyer le type affecté si celui-ci est différent du type lu.
 
Mais surtout, l'objet lu peut être un objet temporaire généré par le compilateur (issu d'une conversion implicite par exemple).
Renvoyer une référence de ce temporaire peut être catastrophique s'il est supprimé par le compilateur dès la première affectation accomplie.

Code :
  1. const A & operator=(const A& other){
  2. return other;
  3. }
  4. A i,j;
  5. i=j=0; //i= peut-être rien !


C'est le fait que l'argument soit const qui autorise à transmettre un temporaire à une référence. Un truc tordu !
 
Donc, on n'a en fait pas le choix si on renvoie des références:

Code :
  1. return *this;


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°284655
galett
Miam Miam des galettes !
Posté le 12-01-2003 à 16:05:22  profilanswer
 

ok, j'ai ma réponse  :)


---------------
mon NAS/HTPC Q11 H55N-USB3, Core i3 http://forum.hardware.fr/hfr/Hardw [...] m#t7599404
n°284660
nraynaud
lol
Posté le 12-01-2003 à 16:23:00  profilanswer
 

Musaran a écrit :


Mais surtout, l'objet lu peut être un objet temporaire généré par le compilateur (issu d'une conversion implicite par exemple).
Renvoyer une référence de ce temporaire peut être catastrophique s'il est supprimé par le compilateur dès la première affectation accomplie.
 
 
Donc, on n'a en fait pas le choix si on renvoie des références:

Code :
  1. return *this;




Tu es très loin de m'avoir convaincu, si le compilo te file à affecter une valeur temporaire (qu'il a créé de façon implicite en plus), il se démerde, c'est à lui de te filer des trucs qui vont durer au moins jusqu'à la fin du scope de la variable.
Par contre, le feit que = renvoie l'ancienne valeur contenue dans la variable et pas la nouvelle, ça me parraît nettement plus grave, c'est une rupture de contrat.

n°284814
LeGreg
Posté le 12-01-2003 à 22:10:37  profilanswer
 

Citation :

Tu es très loin de m'avoir convaincu, si le compilo te file à affecter une valeur temporaire (qu'il a créé de façon implicite en plus), il se démerde, c'est à lui de te filer des trucs qui vont durer au moins jusqu'à la fin du scope de la variable.


 
Oui mais dans ce cas la ce n'est plus la responsabilite du compilateur. L'operateur = est de la responsabilite du programmeur qui l'a surcharge. Et malheureusement on ne peut pas l'empecher d'ecrire n'importe quoi.
 

Citation :

Par contre, le feit que = renvoie l'ancienne valeur contenue dans la variable et pas la nouvelle, ça me parraît nettement plus grave, c'est une rupture de contrat.


 
Ce qui me paraitrait bizarre plutot c'est qu'a la fin de l'operation d'affectation on aurait *this qui vaudrait toujours son ancienne valeur alors que normalement on voudrait qu'elle soit egale a celle de la reference passee en parametre.
 
Bref si l'operateur = est bien ecrit et qu'il renvoie
une reference constante vers *this alors le contrat
est bien respecte imho.
 
LeGreg

n°284816
nraynaud
lol
Posté le 12-01-2003 à 22:25:09  profilanswer
 

legreg a écrit :


Bref si l'operateur = est bien ecrit et qu'il renvoie
une reference constante vers *this alors le contrat
est bien respecte imho.
 


L'ancienne valeur reçoit le message = avec comme argument la nouvelle valeur et, dans la fonction, il n'y a rien de magique qui te permette de faire toi-même l'affectation, par contre on te prévient qu'il y a affectation (de qui sur qui), et que si tu as quelquechose à faire, c'est maintenant ou jamais. On te file pas un pointeur sur la varible et la nouvelle valeur en disant "tiens vas-y affecte", mais on te donne la possibilité de t'accrocher à l'événement affectation.

n°284831
LeGreg
Posté le 12-01-2003 à 22:53:22  profilanswer
 

heink??
 
:crazy:
 
J'ai beau retourner ta phrase dans tous les sens??
 
LeGreg

n°284833
nraynaud
lol
Posté le 12-01-2003 à 22:59:09  profilanswer
 

legreg a écrit :

heink??
 
:crazy:
 
J'ai beau retourner ta phrase dans tous les sens??
 
LeGreg
 


Je réessaye : L'opérateur = n'est pas destiné à faire une affectation. Il sert de handler qui sera appelé au moment de l'affectation, mais on te demande pas physiquement de faire la copie dedans. C'est juste que si tu as un truc à faire au moment de l'affectation, tu le fais dedans, c'est tout.
 
mon vieux pointeurs-intelligents pour un exemple :
http://forum.hardware.fr/forum2.ph [...] t=#t268792

n°284836
LeGreg
Posté le 12-01-2003 à 23:14:38  profilanswer
 

nraynaud a écrit :


Je réessaye : L'opérateur = n'est pas destiné à faire une affectation. Il sert de handler qui sera appelé au moment de l'affectation, mais on te demande pas physiquement de faire la copie dedans. C'est juste que si tu as un truc à faire au moment de l'affectation, tu le fais dedans, c'est tout.


 
Oui mais si lors d'une affectation tu decides de ne rien faire lors de cette affectation c'est tout de meme pervers non ?
 

Citation :

     Pointeur operator = (Pointeur r) { // ici est toute la feinte  
          if (r.real != real) {  
              if (real)  
                  real->unbind();  
              if (r.real)  
                  r.real->bind();  
              real = r.real;  
          }  
          return r;  
      }


 
Quoique j'ai du mal a faire le lien entre ton affirmation
quotee et ce bout de code ou tu fais les choses volontairement mal apparemment mais ca devrait tout de meme marcher (en partie grace aux recopies inutiles..).  
 
LeGreg

n°284847
nraynaud
lol
Posté le 12-01-2003 à 23:43:37  profilanswer
 

legreg a écrit :


 
Oui mais si lors d'une affectation tu decides de ne rien faire lors de cette affectation c'est tout de meme pervers non ?
 

Citation :

     Pointeur operator = (Pointeur r) { // ici est toute la feinte  
          if (r.real != real) {  
              if (real)  
                  real->unbind();  
              if (r.real)  
                  r.real->bind();  
              real = r.real;  
          }  
          return r;  
      }


 
Quoique j'ai du mal a faire le lien entre ton affirmation
quotee et ce bout de code ou tu fais les choses volontairement mal apparemment mais ca devrait tout de meme marcher (en partie grace aux recopies inutiles..).  
 
LeGreg


 
si tu décides de ne rien faire, tu ne fais rien, tu ne surcharges même pas = et ça va s'affecter tout seul (d'ailleur, même si tu surcharges et que tu mets un corps vide ça va le faire aussi), je vois pas la question.
 
Gni ??? c'est n'importe quoi ce code ! Y'a un mec qui m'a fait chier avec des références à la con mais il est pas capable de voir ça.
 
Bon, correction :
 

Code :
  1. Pointeur operator = (Pointeur r) { // ici est toute la feinte
  2.     if (r.real != real) {
  3.       if (real)
  4.         real->unbind();
  5.       if (r.real)
  6.         r.real->bind();
  7.     }
  8.     return r;
  9.   }


 
donc dans cette version, on ne touche pas aux objets eux-même , on ne fait même rien passer de l'un à l'autre, on fait juste des actions justifiées par l'imminence d'une affectation.

n°284850
LeGreg
Posté le 12-01-2003 à 23:48:29  profilanswer
 

ah ben si ca marche apres ta "correction"
ce sera tout de meme un sacre miracle..
 
Bon je retourne bosser. Bonne nuit a vous.
 
LeGreg

n°284870
nraynaud
lol
Posté le 13-01-2003 à 01:18:21  profilanswer
 

Après documentation, je me suis planté.
En fait il assigne tous les champs un par un et il gueule s'il trouve un const ("non-static const member `const int A::i', can't use default assignment operator" ). C'est ce const qui m'a fait planter, je pensais qu'il virait l'objet de la case et qu'il en foutait un nouveau à la place.

n°285061
Musaran
Cerveaulté
Posté le 13-01-2003 à 12:56:10  profilanswer
 

nraynaud a écrit :

si le compilo te file à affecter une valeur temporaire (qu'il a créé de façon implicite en plus), il se démerde, c'est à lui de te filer des trucs qui vont durer au moins jusqu'à la fin du scope de la variable.

Quelle variable ?
Si c'est l'argument de la fonction, c'est le cas : elle est détruite avant même la fin de l'expression.
Si c'est 'i' dans 'i=j=0', ça ne colle pas avec un principe du C++: ce qui se passe après dans l'expression n'influence pas ce qui s'y passe avant.
'i=(j=0)': j=0 produira toujours la même chose, qu'il soit précédé de i= ou pas.
 
Je répète que le mélange valeur temporaire et référence const est... spécial.
Ajouté à l'opérateur = qui est des plus compliqués, c'est pas de la tarte !
 

Citation :

Par contre, le feit que = renvoie l'ancienne valeur contenue dans la variable et pas la nouvelle, ça me parraît nettement plus grave, c'est une rupture de contrat.

Je te comprends pas là.
'return' venant logiquement à la fin de la fonction, l'affectation est accomplie, et la nouvelle valeur (adaptée) renvoyée.
 

Citation :

tu ne surcharges même pas = et ça va s'affecter tout seul (d'ailleur, même si tu surcharges et que tu mets un corps vide ça va le faire aussi)

Non, dès qu'on déclares soi-même l'affectation on est responsable de tout copier.
On peut cependant s'appuyer sur l'affectation de la classe héritée.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°285067
nraynaud
lol
Posté le 13-01-2003 à 13:05:09  profilanswer
 

Musaran a écrit :

Quelle variable ?
Si c'est l'argument de la fonction, c'est le cas : elle est détruite avant même la fin de l'expression.
Si c'est 'i' dans 'i=j=0', ça ne colle pas avec un principe du C++: ce qui se passe après dans l'expression n'influence pas ce qui s'y passe avant.
'i=(j=0)': j=0 produira toujours la même chose, qu'il soit précédé de i= ou pas.
 
Je répète que le mélange valeur temporaire et référence const est... spécial.
Ajouté à l'opérateur = qui est des plus compliqués, c'est pas de la tarte !
 

Citation :

Par contre, le feit que = renvoie l'ancienne valeur contenue dans la variable et pas la nouvelle, ça me parraît nettement plus grave, c'est une rupture de contrat.

Je te comprends pas là.
'return' venant logiquement à la fin de la fonction, l'affectation est accomplie, et la nouvelle valeur (adaptée) renvoyée.
 

Citation :

tu ne surcharges même pas = et ça va s'affecter tout seul (d'ailleur, même si tu surcharges et que tu mets un corps vide ça va le faire aussi)

Non, dès qu'on déclares soi-même l'affectation on est responsable de tout copier.
On peut cependant s'appuyer sur l'affectation de la classe héritée.


 
Laisse tomber, j'ai dit que des conneries, je me suis documenté depuis.


Message édité par nraynaud le 13-01-2003 à 13:06:48
n°287009
karim63
Posté le 15-01-2003 à 18:35:01  profilanswer
 

je voudrais implemetenter une fonctio de recherche, mais assez generale et qui pourrait porter sur des criteres que les objets de la listes doivent avoir.
 
par exemple une methode de recherche qui prend en parametre la valeure recherchée, et aussi l'attribut qui doit avoir cette valeur, ou bien une methode qui renvoit une valeur qui me permettra de faire la comparaison, et la fonction renverrait un pointeur sur cet objet par exemple.
 
si j'ai un objet avec comme attribut int A,B,C de pouvoir faire une recherche en disant sur quel attribut ce fait la recherche, plutot que de devoir faire 3 fonctions de recherche a chaque fois.
C'est possible ?

n°287225
Musaran
Cerveaulté
Posté le 16-01-2003 à 05:14:10  profilanswer
 

Il a posé la question dans un topic à part: http://forum.hardware.fr/forum2.php3?post=30891&cat=10


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°287234
karim63
Posté le 16-01-2003 à 07:49:52  profilanswer
 

quelle balance ce musa  :D

n°288023
Musaran
Cerveaulté
Posté le 17-01-2003 à 05:38:00  profilanswer
 

Tu poses ta question à deux endroits.
Comment se sentirait quelqu'un se donnant la peine de te répondre, pour découvrir que tu as déjà eu une réponse ailleurs ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°288030
karim63
Posté le 17-01-2003 à 07:23:49  profilanswer
 

J'ai cahngé d'avis c tout.
Même si c'est pour continuer ce que j'ai fait dans ce thread, c'est pas forcement le même sujet.
Et pi c'est du second degr&é en plus.  :o

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  comment dupliquer une liste de pointers ? (les objets pointés aussi).

 

Sujets relatifs
liste de choix -> 1 ou tous--> Probleme pour recupérer une valeur dans une liste ! HELP !!!!! <--
Comment recupérer le code d'une liste deroulante?declaration de Liste d'objet
[open gl] affichage d'objets[JS] PB avec la valeur d'une liste
C++ objets et un autre trucfichiers cobol et liste de chansons
queue de messages : liste chainé[OPEN GL] question sur les listes d'objets...
Plus de sujets relatifs à : comment dupliquer une liste de pointers ? (les objets pointés aussi).


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR