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

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

Marsh Posté le 10-01-2003 à 22:14:26    

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
Reply

Marsh Posté le 10-01-2003 à 22:14:26   

Reply

Marsh Posté le 10-01-2003 à 22:20:37    

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

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

Reply

Marsh Posté le 10-01-2003 à 22:22:20    

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
Reply

Marsh Posté le 10-01-2003 à 22:37:20    

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]

Reply

Marsh Posté le 10-01-2003 à 22:43:13    

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 ?

Reply

Marsh Posté le 10-01-2003 à 22:57:42    

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

Reply

Marsh Posté le 10-01-2003 à 23:14:34    

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
Reply

Marsh Posté le 10-01-2003 à 23:50:08    

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
Reply

Marsh Posté le 11-01-2003 à 00:04:34    

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
Reply

Marsh Posté le 11-01-2003 à 00:17:15    

-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;
 
?

Reply

Marsh Posté le 11-01-2003 à 00:17:15   

Reply

Marsh Posté le 11-01-2003 à 00:24:52    

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=)

Reply

Marsh Posté le 11-01-2003 à 00:37:50    

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 ?

Reply

Marsh Posté le 11-01-2003 à 05:47:33    

++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 *) ??

Reply

Marsh Posté le 11-01-2003 à 06:01:31    

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
Reply

Marsh Posté le 11-01-2003 à 07:40:11    

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++

Reply

Marsh Posté le 11-01-2003 à 14:02:54    

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.

Reply

Marsh Posté le 11-01-2003 à 14:43:34    

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).

Reply

Marsh Posté le 11-01-2003 à 14:52:43    

++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

Reply

Marsh Posté le 11-01-2003 à 15:15:17    

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

Reply

Marsh Posté le 11-01-2003 à 15:26:50    

++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)

Reply

Marsh Posté le 11-01-2003 à 21:07:58    

*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
Reply

Marsh Posté le 11-01-2003 à 21:24:38    

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

Reply

Marsh Posté le 12-01-2003 à 04:45:47    

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
Reply

Marsh Posté le 12-01-2003 à 16:05:22    

ok, j'ai ma réponse  :)


---------------
mon NAS/HTPC Q11 H55N-USB3, Core i3 http://forum.hardware.fr/hfr/Hardw [...] m#t7599404
Reply

Marsh Posté le 12-01-2003 à 16:23:00    

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.

Reply

Marsh Posté le 12-01-2003 à 22:10:37    

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

Reply

Marsh Posté le 12-01-2003 à 22:25:09    

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.

Reply

Marsh Posté le 12-01-2003 à 22:53:22    

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

Reply

Marsh Posté le 12-01-2003 à 22:59:09    

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

Reply

Marsh Posté le 12-01-2003 à 23:14:38    

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

Reply

Marsh Posté le 12-01-2003 à 23:43:37    

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.

Reply

Marsh Posté le 12-01-2003 à 23:48:29    

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

Reply

Marsh Posté le 13-01-2003 à 01:18:21    

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.

Reply

Marsh Posté le 13-01-2003 à 12:56:10    

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
Reply

Marsh Posté le 13-01-2003 à 13:05:09    

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
Reply

Marsh Posté le 15-01-2003 à 18:35:01    

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 ?

Reply

Marsh Posté le 16-01-2003 à 05:14:10    

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
Reply

Marsh Posté le 16-01-2003 à 07:49:52    

quelle balance ce musa  :D

Reply

Marsh Posté le 17-01-2003 à 05:38:00    

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
Reply

Marsh Posté le 17-01-2003 à 07:23:49    

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

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed