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

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Suivante
Auteur Sujet :

probleme de hierarchie de classes et copie profonde. [urgent]

n°272454
karim63
Posté le 18-12-2002 à 22:33:36  profilanswer
 

Reprise du message précédent :
c'est ridicule.
Si un objet peut etre identifié a travers son pointeur, dans ce cas y a pas de raison qu'on puisse pas ce servir de la surcharge du + pour additioner deux objets au travers du pointeur.
Ca eviterait de devoir faire *a+*b et en plus ça permettrait de faire facilement ce que j'essayait de faire dans mon prog.
Dans la mesure ou l'adddition des adresses contenue dans deux pointeurs est pas autorisée, je vois pas pkoi les concepteurs ne ce sont pas gardé la possibilité d'additioner deux objets en ne connaissant que leurs pointeurs et leur type. Ca me semble logique ou du moins allant de soit. Dans la mesure ou ça aporte d'autre possiblité je vois pkoi faudrait s'en priver.
le contrat et tout ça c'est du blabla je trouve quand on voit a quel point le c++ est quand même un langage de bidouille.  :jap:

mood
Publicité
Posté le 18-12-2002 à 22:33:36  profilanswer
 

n°272462
nraynaud
lol
Posté le 18-12-2002 à 22:41:05  profilanswer
 

karim63 a écrit :

c'est ridicule.
Si un objet peut etre identifié a travers son pointeur, dans ce cas y a pas de raison qu'on puisse pas ce servir de la surcharge du + pour additioner deux objets au travers du pointeur.
Ca eviterait de devoir faire *a+*b et en plus ça permettrait de faire facilement ce que j'essayait de faire dans mon prog.
Dans la mesure ou l'adddition des adresses contenue dans deux pointeurs est pas autorisée, je vois pas pkoi les concepteurs ne ce sont pas gardé la possibilité d'additioner deux objets en ne connaissant que leurs pointeurs et leur type. Ca me semble logique ou du moins allant de soit. Dans la mesure ou ça aporte d'autre possiblité je vois pkoi faudrait s'en priver.
le contrat et tout ça c'est du blabla je trouve quand on voit a quel point le c++ est quand même un langage de bidouille.  :jap:  


 
Parce que tu n'as pas le droit de changer le comportement d'un opérateur, je te l'ai dit !
 
C'est pêter le contrat est c'est con !  
Le contrat c'est pas du blabla, c'est de la qualité et _tu_ veux faire de la bidouille. C'est peut-être un des seul endroits où on voit le contrat en C++.
 
Si tu veux identifer tes objet par un pointeur sur leur valeur réelle, tu wrappes dans une classe comme ça se fait dans le milieu. Si tu veux faire de la merde, tu ne dis _jamais_ que tu fait de l'objet car c'est une tromperie ! Utiliser le mot clef "class" ne fait pas de toi un concepteur objet.

n°272499
karim63
Posté le 19-12-2002 à 00:00:29  profilanswer
 

le contrat mais je m'en tape.

Citation :

Si tu veux identifer tes objet par un pointeur sur leur valeur réelle, tu wrappes dans une classe comme ça se fait dans le milieu.


 
ca m'interesse par contre.
L'idée m'est venu mais je vois pas trop comment faire.
Surtout que avec ça je pourrais plus declarer mes types normalement.
Enfin bon c pas grave.

n°272538
nraynaud
lol
Posté le 19-12-2002 à 03:05:47  profilanswer
 

karim63 a écrit :

le contrat mais je m'en tape.

Citation :

Si tu veux identifer tes objet par un pointeur sur leur valeur réelle, tu wrappes dans une classe comme ça se fait dans le milieu.


 
ca m'interesse par contre.
L'idée m'est venu mais je vois pas trop comment faire.
Surtout que avec ça je pourrais plus declarer mes types normalement.
Enfin bon c pas grave.


 
 

Code :
  1. class MonEntierAmoi {
  2. private :
  3.   int *entierréel;
  4. public :
  5.   ... <ton bordel>
  6.   MonEntierAmoi (int i):entierréel(new int) {*entierréel = i;}
  7.   ~MonEntierAmoi() {
  8.     delete entierréel;
  9.   }
  10.   MonEntierAmoi operator + (const MonEntierAmoi &autre) {
  11.     return MonEntierAmoi(autre.entierréel + entierréel);
  12.   }
  13. }

 
 
voilà l'idée

n°272543
nraynaud
lol
Posté le 19-12-2002 à 04:17:24  profilanswer
 

nraynaud a écrit :


 
 

Code :
  1. class MonEntierAmoi {
  2. private :
  3.   int *entierréel;
  4. public :
  5.   ... <ton bordel>
  6.   MonEntierAmoi (int i):entierréel(new int) {*entierréel = i;}
  7.   ~MonEntierAmoi() {
  8.     delete entierréel;
  9.   }
  10.   MonEntierAmoi operator + (const MonEntierAmoi &autre) {
  11.     return MonEntierAmoi(autre.entierréel + entierréel);
  12.   }
  13. }

 
 
voilà l'idée


 
Je vais enfoncer le clou entre initialisation et affectation:
 
On remarque que ici, la variable d'instance est initialisée par une allocation et affectée ensuite.
 
En fait c'est plus fin que ça, le type de l'affectaion qui remplacerait l'initialisation serait int * operator =(int*, int*) (enfin si = existe en surcharge extern, ce que j'ai la flemme de vérifier).
Or, le premier paramètre du = (*this si on est dans une classe) est l'ancienne valeur de la variable et celui de droite la future valeur (on doit bien entendu retourner la future valeur).
Si on avait utilisé cet opérateur à la place de l'initialisation, l'opérateur = se serait retrouvé avec à sa gauche un truc qui n'aurait _jamais_ été construit (puisque on est dans le constructeur) donc son état interne est n'importe quoi (en tout cas il a peu de chances de vérifier l'invariant). D'où gros bug.
 
Dans les accolades, l'affectation, elle, est de type int operator =(int, int) donc elle n'est pas du même type que l'initialisation (enfin le machin équivalent mais qui ne l'est pas, vous suivez j'espère !). D'autre part, l'appel à new a implicitement appelé le constructeur sans arguments par défaut sur la cible de la variable d'instance, donc elle _est_ dans un état stable (son invariant est vérifié), on peut donc appeler dessus l'opérateur =.
 
Bien sûr, le mieux est d'appeler directement le bon constructeur :

Code :
  1. class C
  2. private :
  3. T *instance;
  4. public :
  5. C(T &i):instance(new T(i)) {}
  6. ...

 
 
car ici, il n'y a jamais appel à l'opérateur "=".
Mais comme j'ai un doute sur l'existance de constructeurs par copie sur les types primitifs (en fait je pense qu'ils existent), j'ai fait une allocation puis une copie.
 
J'espère que ça peut éclairer du monde sur la nécessité d'utiliser cette notation, et la conditions dans lesquelles on le fait (et le gain de vitesse associé en dehors des bugs évités).


Message édité par nraynaud le 19-12-2002 à 04:22:54
n°272547
Musaran
Cerveaulté
Posté le 19-12-2002 à 06:41:03  profilanswer
 

nraynaud a écrit :

Puis-je juste te suggérer de ne jammais utiliser ça en dehors du débogage, dignostique d'erreur ou exploration (si ça existe en C++, jamais vu avant smalltalk) ou de menaces de mort crédibles ?


toutafé !
Un test de type est un signe de mauvaise conception en C++.
 
Pour les liens, j'ai déjà commencé à lire. Mais j'ai déjà beaucoup de trucs à lire en ce  moment...
 
 
karim63:
typeof sera probablement ajouté au standard et ça m'intéresse pour ecrire des fragments de code génériques sans contexte.
Mais dans cet usage:

Code :
  1. entier* a= ...
  2. typeof(*a)* x  = new typeof(*a)...

Il a recours au type dynamique de *a ?
J'avais pas pensé à ça... et je suis pas sûr que ça me plaise.
 

Citation :

Sauf que operator+ veut pas des pointeurs

Réponse dans ton autre topic: http://forum.hardware.fr/forum2.php3?post=29910&cat=10


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°272800
nraynaud
lol
Posté le 19-12-2002 à 14:26:23  profilanswer
 

Musaran a écrit :


 
karim63:
typeof sera probablement ajouté au standard et ça m'intéresse pour ecrire des fragments de code génériques sans contexte.
Mais dans cet usage:

Code :
  1. entier* a= ...
  2. typeof(*a)* x  = new typeof(*a)...

Il a recours au type dynamique de *a ?
J'avais pas pensé à ça... et je suis pas sûr que ça me plaise.


 
heu les templates et la liaison retardée, c'est fait pour les chevaux que tu essayes d'utiliser un truc batard (typeof) ?

n°273029
edless
Ca serre à quoi une tête
Posté le 19-12-2002 à 16:21:01  profilanswer
 

[citation=269894,1][nom]karim63 a écrit[/nom]bon g mis le code en bas , c pas propre y a des dechets etc.
Alors mon probleme ce trouve au niveau de la surcharge de l'operateur+ .
il y a la class entier dont derivent par heritage les entiers_court puis les entiers normaux, et les entiers longs.
Je voudrais que a+b renvoit un objet du type de a ou même b.
le probleme est que même si je créé un entier_court x avec a et b que je veux le renvoyer avec le return, vu que mon type de retour de la fonction est entier, et bien il me fait une espece de cast automatique et transforme le x en entier :heink: , mais moi je veux pas. :o
 
En fait y a pas moyen de selectionner le type de retour de la fonction. Moi je pensais qu'il m'enverrai l'objet x intact mais nan il fait une conversion du type de x.
Comment empecher cette conversion ?
Merci.
 
 
 
 
 
 
 
 
template?%??

n°273035
edless
Ca serre à quoi une tête
Posté le 19-12-2002 à 16:23:32  profilanswer
 

nraynaud a écrit :


 
Je vais enfoncer le clou entre initialisation et affectation:
 
On remarque que ici, la variable d'instance est initialisée par une allocation et affectée ensuite.
 
En fait c'est plus fin que ça, le type de l'affectaion qui remplacerait l'initialisation serait int * operator =(int*, int*) (enfin si = existe en surcharge extern, ce que j'ai la flemme de vérifier).marche pos
Or, le premier paramètre du = (*this si on est dans une classe) est l'ancienne valeur de la variable et celui de droite la future valeur (on doit bien entendu retourner la future valeur).
Si on avait utilisé cet opérateur à la place de l'initialisation, l'opérateur = se serait retrouvé avec à sa gauche un truc qui n'aurait _jamais_ été construit (puisque on est dans le constructeur) donc son état interne est n'importe quoi (en tout cas il a peu de chances de vérifier l'invariant). D'où gros bug.
 
Dans les accolades, l'affectation, elle, est de type int operator =(int, int) donc elle n'est pas du même type que l'initialisation (enfin le machin équivalent mais qui ne l'est pas, vous suivez j'espère !). D'autre part, l'appel à new a implicitement appelé le constructeur sans arguments par défaut sur la cible de la variable d'instance, donc elle _est_ dans un état stable (son invariant est vérifié), on peut donc appeler dessus l'opérateur =.
 
Bien sûr, le mieux est d'appeler directement le bon constructeur :

Code :
  1. class C
  2. private :
  3. T *instance;
  4. public :
  5. C(T &i):instance(new T(i)) {}
  6. ...

 
 
car ici, il n'y a jamais appel à l'opérateur "=".
Mais comme j'ai un doute sur l'existance de constructeurs par copie sur les types primitifs (en fait je pense qu'ils existent), j'ai fait une allocation puis une copie.
 
J'espère que ça peut éclairer du monde sur la nécessité d'utiliser cette notation, et la conditions dans lesquelles on le fait (et le gain de vitesse associé en dehors des bugs évités).

n°273048
karim63
Posté le 19-12-2002 à 16:28:51  profilanswer
 

ah ouais un template pour operator+ ?

mood
Publicité
Posté le 19-12-2002 à 16:28:51  profilanswer
 

n°273464
Musaran
Cerveaulté
Posté le 20-12-2002 à 00:14:49  profilanswer
 

nraynaud a écrit :

heu les templates et la liaison retardée, c'est fait pour les chevaux que tu essayes d'utiliser un truc batard (typeof) ?


Des fois j'ai besoin de 'petite' généricité sans l'artillerie lourde d'un patron séparé ou de comportements dynamiques.
 
Et pour créer une variable temporaire dans une macro ?
Eh oui, des fois on en a encore besoin...


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°273489
nraynaud
lol
Posté le 20-12-2002 à 01:31:26  profilanswer
 

Musaran a écrit :


Des fois j'ai besoin de 'petite' généricité sans l'artillerie lourde d'un patron séparé ou de comportements dynamiques.
 
Et pour créer une variable temporaire dans une macro ?
Eh oui, des fois on en a encore besoin...


 
Tout vient du fait que tu utilises des macros, arrête et un paquet de tes problèmes vont disparaître.

n°274365
Musaran
Cerveaulté
Posté le 21-12-2002 à 04:42:34  profilanswer
 

Moi je veux bien... mais tu sais mettre ça en patron ?

Code :
  1. #define FOLLOW_AND_FREE(p,mem) (typeof(p) tmp= (p)->mem,free(p),(p)= tmp)

Moi j'ai encore un peu de mal.
 
À part ça j'évites les macros dès que c'est possible, c'est-à-dire presque toujours.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°277291
nraynaud
lol
Posté le 30-12-2002 à 00:23:28  profilanswer
 

Musaran a écrit :

Moi je veux bien... mais tu sais mettre ça en patron ?

Code :
  1. #define FOLLOW_AND_FREE(p,mem) (typeof(p) tmp= (p)->mem,free(p),(p)= tmp)

Moi j'ai encore un peu de mal.
 
À part ça j'évites les macros dès que c'est possible, c'est-à-dire presque toujours.


 
(désolé pour le temps de réponse : fêtes)
 
Première chose : c'est pas de l'objet donc ça n'à rien à foutre sous cette forme en C++ (ça sent très fort la modification de l'état interne de p, donc méthode appliquée sur lui).
 
Deuxième chose : il faut extraire l'interface de FOLLOW_AND_FREEibilité (celui-là je le garde comme néologisme) de tous tes types la supportant.
 
troisième chose : il est hors de question que tu accèdes directement à tes champs de l'extérieur sans passer par un accesseur, donc tu auras des foldChamp1(), foldChamp2() etc.
 
Une proposition :
 

Code :
  1. template<typemachin T> class LinkedList {
  2.   class LinkedElement{
  3.     T content;
  4.     T* next;
  5.   }
  6.   LinkedElement<T> *elems;
  7. public :
  8.   fold() {
  9.     assert(elems != 0);
  10.     LinkedElement<T> temp = elems->next;
  11.     delete(elems);
  12.     elems = temp;
  13.   }
  14. }
  15. class Cerise{}
  16. class Pommes{}
  17. class MaClasse {
  18. private :
  19.   LinkedList<Cerise> cerises;
  20.   LinkedList<Pommes> pommes;
  21. public :
  22.   void foldPommes() {
  23.     pommes.fold();
  24.   }
  25.   void foldCerises() {
  26.     cerises.fold();
  27.   }
  28. }
  29. ...
  30. unMaClasse.foldPommes();
  31. unMaclasse.foldCerises();


 
Je donne à la louche, j'ai rien testé (vu la quantité de code on s'en douterait un peu).
 
Tu remarqueras que la complexité en mémoire est la même qu'avec les notations C associées : pas de liaison retardée, autant d'espace mémoire occupé. On peut remplacer les listes chainées par des vecteurs (par ex.) sans que les utilisateurs de MaClasse n'y voient autre chose qu'une différence de complexité.
 

Code :
  1. struct pomme{}
  2. struct cerise{}
  3. /* souvent, les champs de struct pomme seront directement dans linkedPomme */
  4. struct linkedPomme {
  5.   struct pomme;
  6.   struct linkedPomme pommeSuivante;
  7. }
  8. struct linkedCerise {
  9.   struct cerise;
  10.   struct linkedPomme ceriseSuivante;
  11. }
  12. struct maStruct{
  13. /* faire le parallèle entre "ancreCerises" et LinkedList<Cerise>::elems au-dessus */
  14.   struct linkedCerise *ancreCerises;
  15.   struct linkedPomme *ancrePommes;
  16. };
  17. struct maStruct maVar;
  18. ...
  19. FOLLOW_AND_FREE(maVar, ancreCerises);
  20. FOLLOW_AND_FREE(maVar, ancrePommes);


 
Si j'ai bien compris ta macro (me souviens plus s'il faut des points-virgule à la fin des struct et des classes).
 
Mon exemple ne traduit pas le sens de ta macro "sélection dynamique du champ" afin de garder l'encapsulation et aussi car une opération applicable sur plusieurs types doit être dégagée dans une interface commune (en l'occurence LinkedList).

n°278983
Musaran
Cerveaulté
Posté le 04-01-2003 à 00:10:33  profilanswer
 

Citation :

Première chose : c'est pas de l'objet donc ça n'à rien à foutre sous cette forme en C++ (ça sent très fort la modification de l'état interne de p, donc méthode appliquée sur lui).

Il voit des objets partout !
 

Citation :

Deuxième chose : il faut extraire l'interface de FOLLOW_AND_FREEibilité (celui-là je le garde comme néologisme) de tous tes types la supportant.

Généricité: Il n'y a quasiment pas d'à-priori sur le type manipulable, le contenu de la structure ne nous concerne pas ici.
 

Citation :

troisième chose : il est hors de question que tu accèdes directement à tes champs de l'extérieur sans passer par un accesseur, donc tu auras des foldChamp1(), foldChamp2() etc.

J'avais pas pensé aux accesseurs.
Il faudra deux versions: avec ou sans accesseur, vu que C++ ne permet pas les accesseurs transparents.
 
 
Il ne s'agit pas de créer une classe disposant d'une méthode pour cette action, mais de pouvoir appliquer cet algorithme à n'importe quelle classe disposant d'un pointeur de son propre type (ou assimilable).
 
Le but est de pouvoir réunir ces trois lignes en une instruction, et donc pouvoir la mettre à sa place dans le for:

Code :
  1. struct node{
  2. node* next;
  3. node* getnext() const{ return next;} //accesseur
  4. };
  5. for(node* pnode= ... ; pnode!=0 ; ){ //parcourir et désallouer une liste chaînée
  6. //...
  7. node* ptemp= pnode->next; //1 [ou getnext()]
  8. delete pnode; //2
  9. pnode= ptemp; //3
  10. }


J'ai finalement réussi à faire ça:

Code :
  1. template <typename T, typename X> // //type du node et du membre
  2. void follow_and_delete(T*& pointer,X* T::* ptrmember){
  3. T* temp= pointer->*ptrmember;
  4. delete pointer;
  5. pointer= temp;
  6. }
  7. template <typename T, typename X> // //type du node et type déclarateur du membre
  8. void follow_and_delete(T*& pointer,X* (T::* ptrmemberfunc)() const ){
  9. T* temp= (pointer->*ptrmemberfunc)();
  10. delete pointer;
  11. pointer= temp;
  12. }
  13. ...
  14. for(node* pnode= ... ; pnode!=0 ; follow_and_delete(pnode, &node::next)){ //ou getnext
  15. //...
  16. }

C'est pas aussi simple d'emploi que la macro: il faut spécifier '&node::'.
J'ai bien essayé de prendre cet argument par référence, mais les références sur membres n'existent pas.
 
Sérieusement, un pointeur sur fonction membre comme argument formel d'une fonction patronée servant à parcourir destructivement une liste chaînée, c'est bien le truc le plus :pt1cable: que j'aie jamais fait en C++.
Il m'a fallu 3 heures pour y arriver...
 
 
 
Mais j'insiste: il y a des choses que seule la macro peut faire:

Code :
  1. struct coord3d{
  2. float x, y, z;
  3. };
  4. coord3d une_coord= {...};
  5. void func(float fx, float fy, float fz);
  6. func(une_coord.x, une_coord.y, une_coord.z); //pénible
  7. #define DROP_xyz(st) st.x, st.y, st.z
  8. func(DROP_xyz(une_coord)); //plus simple


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°278993
LeGreg
Posté le 04-01-2003 à 00:25:40  profilanswer
 

les macros c'est un outil de processing de texte
donc c'est normal qu'il y a des choses qu'on
fait en macros qu'on ne peut pas faire avec les  
constructions standards du C++
 
A part preprocesser a la main mais c'est pas une option.
 
LeGreg


---------------
voxel terrain render engine | animation mentor
n°279802
nraynaud
lol
Posté le 05-01-2003 à 23:01:40  profilanswer
 

Musaran a écrit :


 

Citation :

Deuxième chose : il faut extraire l'interface de FOLLOW_AND_FREEibilité (celui-là je le garde comme néologisme) de tous tes types la supportant.

Généricité: Il n'y a quasiment pas d'à-priori sur le type manipulable, le contenu de la structure ne nous concerne pas ici.
 
Il ne s'agit pas de créer une classe disposant d'une méthode pour cette action, mais de pouvoir appliquer cet algorithme à n'importe quelle classe disposant d'un pointeur de son propre type (ou assimilable).
 


 
tu te réponds à toi-même : tu veux que toutes les classes disposant d'un pointeur sur leur propre type (on appelle ça une liste chainée) disposenent d'un comportement commun (un ensemble d'objet ayant un comportement commun est une classe).
Le principe de l'objet t'oblige à dégager les comportements communs.
 
Un petit Martin pour la route (je vais peut-être foutre toute la liste dans ma signature un jour) : http://www.objectmentor.com/resour [...] derlay.pdf
il est malheureusement un peu plus évolué que ce problèmes de listes chaînées mais il montre bien comment ressortir les comprtements communs.

n°279864
Musaran
Cerveaulté
Posté le 06-01-2003 à 07:45:06  profilanswer
 

Je veux pouvoir le faire sur tous les types, y compris ceux que je n'aurais pas conçus.
Donc, je dégage ce comportement non pas comme une méthode d'objet mais comme un algorithme générique.
 
Je pourrais faire une classe iterator_deleter surchargeant ++ pour cette opération, le code utilisateur serait allégé mais moins explicite.

Code :
  1. template <typename T, typename X>
  2. class iterator_deleter{
  3. T* pointer_;
  4. X* T::* ptrmember_;
  5. public:
  6. iterator_deleter(T* pointer,X* T::* ptrmember); //construction
  7. //todo: recopie et affectation à partir de T*, cast vers T*
  8. //todo: surcharger * et ->pour mimer un pointeur
  9. iterator_deleter& operator ++(){
  10.  T* temp= pointer_->*ptrmember_;
  11.  delete pointer_;
  12.  pointer_= temp;
  13.  return *this;
  14. }
  15. };
  16. for(iterator_deleter<node,&node::next > pnode= ... ; pnode!=0 ; ++pnode)

J'ai pas testé, mais ça fait des complications pour un truc simple tous ça.
 
(Je lis ton lien de ce pas)


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°280096
nraynaud
lol
Posté le 06-01-2003 à 14:46:21  profilanswer
 

Musaran a écrit :

Je veux pouvoir le faire sur tous les types, y compris ceux que je n'aurais pas conçus.


 
Ca m'étonnerait que tu trouves beaucoup d'application écrites par des non-débutants (ou gros-nazes vétérans aussi, j'en connais) qui n'utilisent pas une classe séparée pour ce genre de trucs. Au moins ils te filerons une collection avec des accesseurs (si elle est modifiable mais bon implanter une collec non-modifiable par une liste chaînée relève de la psychose ou du cas hyper exceptionel).
 

Citation :


(Je lis ton lien de ce pas)


 
tiens, lis-en un à chaque fois que tu vas au chiottes :  
http://www.objectmentor.com/resour [...] .%20Martin
 
(merde y'a des nouveaux, va falloir que j'aille chier)

n°281620
karim63
Posté le 07-01-2003 à 23:42:01  profilanswer
 

ça marche pas un bidule que je fé. :cry:  
 

Citation :

pieces.cpp: In method `piece_composite::piece_composite(const piece_composite &)
':
pieces.cpp:43: no matching function for call to `piece::piece ()'
pieces.cpp:11: candidates are: piece::piece(basic_string<char,string_char_traits
<char>,__default_alloc_template<false,0> >, int)
pieces.cpp:16:                 piece::piece(const piece &)
pieces.cpp:45: no matching function for call to `piece::piece ()'
pieces.cpp:11: candidates are: piece::piece(basic_string<char,string_char_traits
<char>,__default_alloc_template<false,0> >, int)
pieces.cpp:16:                 piece::piece(const piece &)


 

Code :
  1. #include <iostream>
  2. #include <string>
  3. class piece
  4. {
  5. protected:
  6.   string nom;
  7.   int reference;
  8.   int prix;
  9.   public:
  10.   piece(string _nom,int _reference)
  11.   {
  12.     nom=_nom;
  13.     reference=_reference;
  14.   };
  15.   virtual int getprix();
  16. };
  17. class piece_simple: public piece
  18. {
  19. public:
  20.   piece_simple(string _nom,int _reference,int _prix):piece(_nom,_reference)
  21.   {
  22.     prix=_prix;
  23.   };
  24.  
  25.   int getprix(){return prix;};
  26. };
  27. class piece_composite :public piece
  28. {
  29. protected:
  30.   piece* composants;
  31.   int nbcomposants;
  32. public:
  33.   piece_composite(string _nom,int _reference):piece(_nom,_reference)
  34.   {
  35.     nbcomposants=0;
  36.     composants=0;
  37.   };
  38.  
  39.   piece_composite(const piece_composite &pc)
  40.   {
  41.     nbcomposants=pc.nbcomposants;
  42.     composants=new piece [nbcomposants];
  43.     for(int i=0;i<nbcomposants;i++)
  44.       {
  45. composants[i]=pc.composants[i];
  46.       };
  47.   };
  48.    
  49. /*
  50.   piece_composite& operator=(const piece_composite &pc)
  51.   {
  52.     nbcomposants=pc.nbcomposants;
  53.     delete [] composants;
  54.     composants=new piece [nbcomposants];
  55.     for(int i=0;i<nbcomposants;i++)
  56.       {
  57. composants[i]=pc.composants[i];
  58.       };
  59.     return *this;
  60.   };
  61.    
  62.   ~piece_composite()
  63.   {
  64.     delete [] composants;
  65.   };
  66.    
  67.   void ajoutercomposante(const piece &pc)
  68.   {
  69.     piece* aux=new piece[nbcomposants+1];
  70.     for(int i=0;i<nbcomposants;i++)
  71.       {
  72. aux[i]=composants[i];
  73.       };
  74.     ++nbcomposants;
  75.     aux[nbcomposants-1]=pc;
  76.     delete [] composants;
  77.     composants=aux;
  78.   };
  79.   virtual int getprix();
  80. */
  81. };
  82. /*
  83.   class piece_composite_kit: public piece_composite
  84. {
  85. public:
  86.   int getprix()
  87.   {
  88.     prix=0;
  89.     for(int i=0;i<nbcomposants;i++)
  90.       {
  91. prix+=composants[i].getprix();
  92.       };
  93.   };
  94. };
  95. class piece_composite_assemblee :public piece_composite
  96. {
  97. public:
  98.   int getprix();
  99. };
  100. */
  101. main()
  102. {
  103. }

n°281628
karim63
Posté le 08-01-2003 à 00:01:46  profilanswer
 

bon benh je me reponds a moi même.
En fait fallait mettre le constructeur piece(); sans arguments.
Je comprends pas trop, vu que tout ce que je fait c'est declarer un type pour les tableau par exemple : new piece [] .

n°281643
karim63
Posté le 08-01-2003 à 00:43:44  profilanswer
 

donc voilà encore une fois ça ne marche pas.
Et je me retrouve encore confronté exactement au même probleme,
qui vient ici a mon avis du tableau de pieces.
Franchement je compred pas pkoi y a une telle limitation ou alors je tripe vraiment.
 

Code :
  1. #include <iostream>
  2. #include <string>
  3. static const int maindoeuvre=100;
  4. class piece
  5. {
  6. protected:
  7.   string nom;
  8.   int reference;
  9.   int prix;
  10.   public:
  11.   piece();
  12.   piece(string _nom,int _reference)
  13.   {
  14.     nom=_nom;
  15.     reference=_reference;
  16.   };
  17.   piece(const piece &pc)
  18.   {
  19.     nom=pc.nom;
  20.     reference=pc.reference;
  21.     prix=pc.prix;
  22.   };
  23.   virtual int getprix(){};
  24. };
  25. class piece_simple: public piece
  26. {
  27. public:
  28.   piece_simple(string _nom,int _reference,int _prix):piece(_nom,_reference)
  29.   {
  30.     prix=_prix;
  31.   };
  32.  
  33.   int getprix(){return prix;};
  34. };
  35. class piece_composite :public piece
  36. {
  37. protected:
  38.   piece* composants;
  39.   int nbcomposants;
  40. public:
  41.   piece_composite(string _nom,int _reference):piece(_nom,_reference)
  42.   {
  43.     nbcomposants=0;
  44.     composants=0;
  45.   };
  46.  
  47.   piece_composite(const piece_composite &pc)
  48.   {
  49.     nbcomposants=pc.nbcomposants;
  50.     composants=new piece [nbcomposants];
  51.     for(int i=0;i<nbcomposants;i++)
  52.       {
  53. composants[i]=pc.composants[i];
  54.       };
  55.   };
  56.  
  57.   piece_composite& operator=(const piece_composite &pc)
  58.   {
  59.     nbcomposants=pc.nbcomposants;
  60.     delete [] composants;
  61.     composants=new piece [nbcomposants];
  62.     for(int i=0;i<nbcomposants;i++)
  63.       {
  64. composants[i]=pc.composants[i];
  65.       };
  66.     return *this;
  67.   };
  68.  
  69.   ~piece_composite()
  70.   {
  71.     delete [] composants;
  72.   };
  73.  
  74.   void ajouter(const piece &pc)
  75.   {
  76.     piece* aux=new piece[nbcomposants+1];
  77.     for(int i=0;i<nbcomposants;i++)
  78.       {
  79. aux[i]=composants[i];
  80.       };
  81.     ++nbcomposants;
  82.     aux[nbcomposants-1]=pc;
  83.     delete [] composants;
  84.     composants=aux;
  85.   };
  86.   virtual int getprix(){};
  87. };
  88. class piece_composite_kit: public piece_composite
  89. {
  90. public:
  91.  
  92.   piece_composite_kit(string _nom,int _reference):piece_composite(_nom,_reference)
  93.   {
  94.   };
  95.   int getprix()
  96.   {
  97.     prix=0;
  98.     for(int i=0;i<nbcomposants;i++)
  99.       {
  100. prix+=composants[i].getprix();
  101.       };
  102.     return prix;
  103.   };
  104. };
  105. class piece_composite_assemblee :public piece_composite
  106. {
  107. public:
  108.   piece_composite_assemblee(string _nom,int _reference):piece_composite(_nom,_reference)
  109.   {};
  110.   int getprix()
  111.   {
  112.     prix=0;
  113.     for(int i=0;i<nbcomposants;i++)
  114.       {
  115. prix+=composants[i].getprix();
  116.       };
  117.     prix+=maindoeuvre;
  118.    
  119.     return prix;
  120.   };
  121. };
  122. main()
  123. {
  124.   piece_composite_assemblee x ("roue de brouette en kit",11512);
  125.   piece_simple a ("pneu",4741,40);
  126.   piece_simple b ("rayon",4748,10);
  127.   piece_simple c ("rayon",4748,10);
  128.   piece_simple d ("rayon",4748,10);
  129.   piece_simple e ("chambre a air",4565,15);
  130.   piece_simple f ("disque de jante",1214,25);
  131.  
  132.   piece_composite_assemblee g ("jante",4748);
  133.  
  134.   g.ajouter(b);
  135.   // g.ajouter(c);
  136.   // g.ajouter(d);
  137.   //  g.ajouter(f);
  138.   //  x.ajouter(g);
  139.   // x.ajouter(a);
  140.   // x.ajouter(e);
  141.  
  142.   cout << b.getprix();
  143. }

n°281676
nraynaud
lol
Posté le 08-01-2003 à 01:23:32  profilanswer
 

karim63 a écrit :

bon benh je me reponds a moi même.
En fait fallait mettre le constructeur piece(); sans arguments.
Je comprends pas trop, vu que tout ce que je fait c'est declarer un type pour les tableau par exemple : new piece [] .


 
C'est là toute la feinte, un objet est obligatoirement _construit_ ie alloué _et_ initialisé (mis dans un état stable, qui vérifie l'invariant).  
Ecrire new Object[nbelem] n'alloue pas un tableau d'objets mais construit une série d'objets indicés par des entiers. Comme il n'existe pas de syntaxe pour passer des paramètres à chacun les constructeurs qui on étés appellés, le compilo appelle forcément le constructeur sans argument Object() dans mon exemple sur chaque objet nouvellement construit.
 
Ceci implique plusieurs choses : les objets pour lesqel un constructeur sans argument n'existe pas (sa présence n'a pas de sens par ex., style des personnes dont le nom est obligatoire) ne peuvent être construits par cette syntaxe, l'autre sens, si tu prévois de faire des tableaux d'instances de ta classe, il faut lui mettre un constructeur sans arguments. Cependant, ne l'écrit pas systématiquement : ce constructeur a-t'il du sens ou pas ?
 
Pour les classes où il n'y a pas de constructeur sans arguments, il faut construire tes objets avant de les foutre dans la collection (par copie par exemple, la présence ou l'absence d'un constructeur sans arguments est indépendante de la présence ou l'absence d'un constructeur par copie).
 
Au passage, la présence ou non d'un constructeur par copie est aussi à discuter au cas-par-cas, à la louche je ne vois que le cas du pattern singleton (la classe ne possède qu'une seule instance dans tout le système, donc un seul état interne possible, donc aucune variable d'instance, comme true, false et nil en smalltalk ou Void en Eiffel) et du pattern flywheight (la classe possède au plus une instance dans chaque état possible, comme Character et SmallInteger en smalltalk) qui justifient l'absence de constructeur par copie (et de swap et de toute "relocation" en général), dans les 2 cas, les objets sont immuables (il est impossible de modifier leur état interne, il n'existe pas d'accesseur en écriture, toutes les méthodes sont déclarée "const" ). De tête, je pense qu'il est plus rare de ne pas avoir de constructeur par copie que de ne pas avoir de constructeur sans arguments.
 
edit : changé la phrase expliquant new []


Message édité par nraynaud le 08-01-2003 à 02:01:26
n°281686
karim63
Posté le 08-01-2003 à 01:39:43  profilanswer
 

merci pour tes explications. (pourrais tu etre un peu plus concret dans tes explications stp ? )
Tout est pas clair, mais en gros que dois je faire ?
tout ce que je vois serait de faire un tableau de pointeurs sur des objets pieces.
par exemple  

Code :
  1. piece** tab [];
  2. tab =new piece*[x];


et pour rajouter l'objet benh là ché pas [:ddr555]
Si comme ça avec o l'objet passé en parmatre de ma methode et de type piece :
 

Code :
  1. tab[z]=new piece = o ;


 
 :heink:  
 
Sauf que apres en voyant ça je me dit quel est l'interet du c++ ?
autant faire du java vu que y a le garbage colector.
car la si je veux effacer mon tableau fo que je fasse:

Code :
  1. for(int i=0;i<nbelemetableau;i++)
  2. {
  3. delete tab[i];
  4. };
  5. }


 
en gros faudrait que je surcharge l'operateur delete pour le type piece** [] ?

n°281700
nraynaud
lol
Posté le 08-01-2003 à 03:17:54  profilanswer
 

karim63 a écrit :

merci pour tes explications. (pourrais tu etre un peu plus concret dans tes explications stp ? )
Tout est pas clair, mais en gros que dois je faire ?
tout ce que je vois serait de faire un tableau de pointeurs sur des objets pieces.
par exemple  

Code :
  1. piece** tab [];
  2. tab =new piece*[x];


et pour rajouter l'objet benh là ché pas [:ddr555]
Si comme ça avec o l'objet passé en parmatre de ma methode et de type piece :
 

Code :
  1. tab[z]=new piece = o ;


 
 :heink:  
 
Sauf que apres en voyant ça je me dit quel est l'interet du c++ ?
autant faire du java vu que y a le garbage colector.
car la si je veux effacer mon tableau fo que je fasse:

Code :
  1. for(int i=0;i<nbelemetableau;i++)
  2. {
  3. delete tab[i];
  4. };
  5. }


 
en gros faudrait que je surcharge l'operateur delete pour le type piece** [] ?


 
 
Je viens de lire ton code, il me semble qu'une pièce sans prix, référence, nom etc. n'a pas de sens de même qu'une valeur par défaut n'en aurait pas.
 
Tu _dois_ donc construire chaque pièce comme il faut (constructeur avec arguments).
 
Fait gaffe, je viens de voir des "=" dans tes constructeurs, j'ai déjà expliqué pourquoi il ne fallait pas en mettre pour initialiser les variables d'instance mais utilser la syntaxe d'initialisation (d'autre part, vous plaignez pas que C++ soit lent après).
 
Je suppose que tu es au courrant qu'il existe des collections dans la STL, elles vont résoudre ton pb, elle ont des méthodes pour insérer une à une tes pièces dans ta collection.
 
je cherche mon poly sur vector ...
 

Code :
  1. #include <vector>
  2. #include <iterator>
  3. #include <iostream>
  4.   #include <string>
  5.  
  6. //il y a un truc à foutre ici pour rentrer dans l'espace de nom standard genre "use namespace std;" syntaxe à vérifier.
  7.   static const int maindoeuvre=100;
  8.  
  9.   class piece
  10.   {
  11.     protected:
  12.       string nom;
  13.       int reference;
  14.       //je vire le prix, les composites n'en ont pas (de prix propre, elles ont le prix de leurs constituants)
  15.     public:
  16.       piece();
  17.       piece(string _nom,int _reference): nom(_nom), reference(_reference)
  18.       {}; // initialisation, pas affectation, tu me le copieras 100 fois !!!
  19.       piece(const piece &pc): nom(pc.nom), reference(pc.reference) {}; // pareil
  20.       virtual int getprix() const = 0; // s'il n'y a pas de code, c'est une fonction abstraite (sans corps) matte la notation pourrie ! ne ne mets pas de "{}" mais "= 0" (égal zéro) ; tu obligeras les sous-classes à lui donner du code. Au lieu de risquer d'oublier et de renvoyer n'importe quel int sur la pile, ce qui est dommage pour un prix
  21. //le const est là pour dire que demander le prix ne change pas l'état interne de l'objet
  22.   };
  23.  
  24.   class piece_simple: public piece
  25.   {
  26.     protected :
  27.       int prix;
  28.     public:
  29.       piece_simple(string _nom,int _reference,int _prix):p iece(_nom,_reference), prix(_prix) //pareil initialisation
  30.       {}; 
  31.       int getprix() const {return prix;};
  32.   };
  33. class piece_composite :public piece
  34. {
  35. protected:
  36. //ici cette notation peut parfois être lourde (en particulier avec des itérateurs), tu peux utiliser un typedef pour "instancier" ton type, à la Ada : typedef vector<piece> pieces ; retiens-le surtout lorsque tu auras des templates à plusieurs arguments.
  37. vector<piece> composants;
  38. piece_composite(string _nom,int _reference):piece(_nom,_reference) {/*on vire les affectations qui n'avaient rien à foutre là de toute façon */};
  39. piece_composite(const piece_composite &pc): piece(pc), composants(pc.composants) {}; // c'est ça l'initialisation, comme l'appel du constructeur parent (c'est la même chose en fait) que tu avais oublié
  40. }
  41. // on vire la copie profonde
  42. // on vire le destructeur
  43. void ajouter(const piece &pc)
  44. {
  45.    composants.push_back(piece);
  46. };
  47. }
  48.  
  49.   class piece_composite_kit: public piece_composite
  50.   {
  51.     public:
  52.      
  53.       piece_composite_kit(string _nom,int _reference):piece_composite(_nom,_reference)
  54.       {
  55.       };
  56.    
  57.       int getprix() const
  58.       {
  59.          int prix=0;
  60.          // regarde la syntaxe des iterateurs sur collection
  61.          // le "::" est l'opérateur pour aller chercher un truc dans un espace de nom, un va chercher le type iterator dans l'espace de nom vector<piece> l'iterateur sera bien entendu déjà spécialisé à sa sortie.
  62.          for(vector<piece>::iterator i = composants.begin(); i != composants.end(); i++)
  63.             {
  64.          prix += *i.getprix(); //la syntaxe (*i) correspond à l'élément courant dans l'iterateur, comme si l'itérateur était un pointeur (i++, i* etc.)
  65.             };
  66.           return prix;
  67.       };
  68.   };
  69.  
  70. //je change la hiérarchie en disant qu'une piece composite assemblée, c'est un kit et de la main d'oeuvre, je vais avoir certains comportement communs
  71. //de façon moins avouable, je récupère le code de getprix() du kit
  72. //c'est une _très_ mauvaise idée, voir plus bas
  73.   class piece_composite_assemblee :public piece_composite_kit
  74.   {
  75.     int maindoeuvre; //prix de la main d'oeuvre
  76.     public:
  77.       piece_composite_assemblee(string _nom,int _reference):p iece_composite_kit(_nom,_reference) {}; //répercution du changement de hiérarchie
  78.       int getprix()
  79.       {
  80.           /*aïlle, je suis pas sûr d'avoir été malin sur ce coup là ! il a vraiment une sale tête et sent le truc super dangereux ... bon vu l'heure, je te laisse corriger, je pense qu'il faut que cette classe aggrège un kit et de la main d'oeuvre, mais il faut virer les variables d'instance de la classe piece et ne garder que l'interface, pour ne pas avoir 1 fois le nom etc. (dans le kit et dans la piece assemblée)*/
  81.           return piece_composite_kit::getprix() + maindoeuvre;
  82.       };
  83.   };
  84.   main()
  85.   {
  86.       piece_composite_assemblee x ("roue de brouette en kit",11512);
  87.       piece_simple a ("pneu",4741,40);
  88.       piece_simple b ("rayon",4748,10);
  89.       piece_simple c ("rayon",4748,10);
  90.       piece_simple d ("rayon",4748,10);
  91.       piece_simple e ("chambre a air",4565,15);
  92.       piece_simple f ("disque de jante",1214,25);
  93.      
  94.       piece_composite_assemblee g ("jante",4748);
  95.      
  96.       g.ajouter(b);
  97.       // g.ajouter(c);
  98.       // g.ajouter(d);
  99.       //  g.ajouter(f);
  100.       //  x.ajouter(g);
  101.       // x.ajouter(a);
  102.       // x.ajouter(e);
  103.      
  104. // 'va peut-être falloir donner des prix à tout le monde avant de faire ça mon gars !!
  105. // t'as tous tes constructeurs à modifier !
  106.       cout << b.getprix();
  107.    
  108.   }


 
bon, je voulais t'en filer qu'un morceau mais y'avait trop de trucs que je voulais te montrer... Mais je te laisse le meilleur : j'ai rien compilé (et avec la fatigue, le taux de conneries à la minute augmente), c'est pas fini et t'as rien pour donner des prix.
 
edit (pour répondre aux autres points) :
Arrête de vouloir surcharger des opérateurs, c'est hyper casse-gueule et si tu débutes, tu va te tirer une balle dans le pied.
 
Sinon, les tableaux n'ont pas grand'chose d'objet, c'est pour ça qu'ils foutent souvent la merde dans les applications, évite de les utiliser explicitement. On les utilise pour faire des collections mais pas directement ailleur.  
 


Message édité par nraynaud le 08-01-2003 à 03:36:44
n°281704
Musaran
Cerveaulté
Posté le 08-01-2003 à 04:07:49  profilanswer
 

Edit: J'arrives après la bataille...
 
Mais de quel droit tu postes dans cette conversation privée :D ?
 
C'est pourtant simple...
Piece a un constructeur, il doit obligatoirement être construit.
Et là:

Code :
  1. new piece [nbcomposants];

D'abord tu ne fournis pas d'arguments pour le constructeur, ensuite C++ ne le permet pas avec new[]. Dans le futur peut-être ?
 
piece doit avoir un constructeur par défaut:
-soit sans argument.
-soit des valeurs par défaut pour tous les arguments.
-soit aucun constructeur.


Message édité par Musaran le 08-01-2003 à 04:19:36

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°281810
Kristoph
Posté le 08-01-2003 à 11:07:31  profilanswer
 

La réponse est encore plus simple : n'utilises pas new aaa[] mais fait appel a std::vector. Tu veras ca te simplifiera la vie.
 
Pour les opérateurs +, la méthode standard en C++ et la plus efficace c'est de :
 
const entier operator+(const entier &, const entier &); en fonction friend et tu la redefinie pour chaque type derivé avec le bon typage
 
Voici ce qui se passe pour le code de ce genre :
entier a(20);
a = 22;
 
Tentative d'affectation de int dans un entier. Recherche d'une chaine de convertion de int vers entier. Il trouve le constructeur suivant : entier::entier(int) et donc il remplace le code par :
 
a = entier(22);

n°282295
karim63
Posté le 09-01-2003 à 00:26:25  profilanswer
 

Kristoph a écrit :

La réponse est encore plus simple : n'utilises pas new aaa[] mais fait appel a std::vector. Tu veras ca te simplifiera la vie.
 
Pour les opérateurs +, la méthode standard en C++ et la plus efficace c'est de :
 
const entier operator+(const entier &, const entier &); en fonction friend et tu la redefinie pour chaque type derivé avec le bon typage
 
Voici ce qui se passe pour le code de ce genre :
entier a(20);
a = 22;
 
Tentative d'affectation de int dans un entier. Recherche d'une chaine de convertion de int vers entier. Il trouve le constructeur suivant : entier::entier(int) et donc il remplace le code par :
 
a = entier(22);
 


 
oui mais si je te montre le sujet, tu verrais que c pas ausssi simple.
 
pour les classes vector, effectivement je devrais mais bon on devrait etre capable par exemple de creer notre propre classe vector.
Et puis bon chui là pour m'embeter justement.
Face a un prob c un peu simple d'utiliser les solutions des autres. Pas les votres, mais celle deja prémachées par les librairie. Enfin là c pas la mort de faire son propre type liste ou vecteur.
Enfin aussi ça m'interesse de comprendre pkoi certains trucs passent et d'autres pas.
Merci pour ton aide  :jap:

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
Cherche WEBMASTER URGENT !!!!Problème sur un devoir en assembleur [Help : c'est pas simple <:'o( ]
[ Les Classes et la POO ] quelqu un dans la salle ?Assez Urgent : Scrolling de frame
question bete : probleme dans la déclaration d'un tableau[ACCESS] Problème de requette
Requête SQL sur controle ADO - Problème[JAVA] Problème avec javax.servlet :/
[JS] Petit probleme de retour à la window par défaut apres un popup[ASP] Pb d'affichage des zones de texte [URGENT]
Plus de sujets relatifs à : probleme de hierarchie de classes et copie profonde. [urgent]


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