| |||||
| Dernière réponse | |
|---|---|
| Sujet : [C++] VCC capricieux, et borland.... | |
| slvn | bon, donc faut pas que je me fasse d illusions quant aux performances de mes nouveaux operateurs alors :( pour les constructeurs, j avais entendu dire, qu on pouvait les utiliser en plein milieu du prog, par ex, ca facilitait le codage d une liste chainée (lorsqu on detruit, on recolle la chaine au meme moment). mais de toute facon, ce qui prendra le plus de place, ce n est pas les objet, mais le tableau de char, pointé par "nb", donc au pire, je ferais une fonction, qui ne servira que pour faire un "delete [] nb". sinon, pile/tas, c est par rapport aux notions d asm ?? (la pile stock les variables locales, l adresse de la fonction, les parametres de la fonction, et le tas stocke les constantes?) je viens, de resoudre les pb de "plantage" sous borland, en rajoutant les parametres " ......(const HugeInt&) const" ..etant donné que j ai pas changé le code du prog je vois pas ce que ca a pu faire de plus, enfin, j ai peut etre une idée : si je fait : void fonction( HugeInt a); fonction(aaaaaa); le prog, fait une copie locale du parametre effectif aaaaaa. cette copie est utilisée au cours de la fonction, et est detruite a la fin -> d apres, le destructeur, il y a destruction et libereration de la zone memoire pointée par les pointeurs de la copie de aaaaaa. et vu que les pointeurs de la copie ont meme valeur que les pointeurs de aaaaaa, alors le destructeurs va libere la memoire de aaaaaaa aussi ? donc en utilisant une reference, y a pas destructions, donc pas d erreur:??: c pas facil d etre clair lol |
| Aperçu |
|---|
| Vue Rapide de la discussion |
|---|
| slvn | bon, donc faut pas que je me fasse d illusions quant aux performances de mes nouveaux operateurs alors :( pour les constructeurs, j avais entendu dire, qu on pouvait les utiliser en plein milieu du prog, par ex, ca facilitait le codage d une liste chainée (lorsqu on detruit, on recolle la chaine au meme moment). mais de toute facon, ce qui prendra le plus de place, ce n est pas les objet, mais le tableau de char, pointé par "nb", donc au pire, je ferais une fonction, qui ne servira que pour faire un "delete [] nb". sinon, pile/tas, c est par rapport aux notions d asm ?? (la pile stock les variables locales, l adresse de la fonction, les parametres de la fonction, et le tas stocke les constantes?) je viens, de resoudre les pb de "plantage" sous borland, en rajoutant les parametres " ......(const HugeInt&) const" ..etant donné que j ai pas changé le code du prog je vois pas ce que ca a pu faire de plus, enfin, j ai peut etre une idée : si je fait : void fonction( HugeInt a); fonction(aaaaaa); le prog, fait une copie locale du parametre effectif aaaaaa. cette copie est utilisée au cours de la fonction, et est detruite a la fin -> d apres, le destructeur, il y a destruction et libereration de la zone memoire pointée par les pointeurs de la copie de aaaaaa. et vu que les pointeurs de la copie ont meme valeur que les pointeurs de aaaaaa, alors le destructeurs va libere la memoire de aaaaaaa aussi ? donc en utilisant une reference, y a pas destructions, donc pas d erreur:??: c pas facil d etre clair lol |
| LeGreg |
|
| LeGreg |
|
| slvn | si j ai besoin de reccuperer de la memoire en plein milieu du prog, faut bien que je fasse appelle au destructeur moi meme ??
le delete[] ne change rien....(j aurais meme tendance a dire que delete[] == delete, enfin d apres vu sur un bouquin, ils se servait aussi bien de l un comme de l autre pour reccuperer la memoire de leur tableau) sinon, bien vu pour le coup du a=a; ;) |
| verdoux | Et dans ton opérateur d'affectation, tiens compte du cas:
a = a; [jfdsdjhfuetppo]--Message édité par Verdoux--[/jfdsdjhfuetppo] |
| verdoux | Certes, mais c'est dans 99% des cas une mauvaise idée car le compilo l'appelle déjà pour toi.
Et puis, comme signalé précédemment remplace delete nb par delete[] nb |
| slvn | je debute en C++ et j essayais de tester les trucs par moi meme :)
...je voulais savoir si on pouvais utiliser les destructeurs, en plein milieu du prog :) je crois que oui. d ailleurs, apres verification, le prog du dessus marche bien avec VCC mais plante(a la fin de l execution) avec Borland (quand le delete du constructeur est activé) |
| verdoux | Pourquoi appelles-tu les destructeurs toi-même ? |
| slvn | voici le bazaar :
(qui fait planter le prog sous borland a cause du delete du constructeur......) (:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o: o:o:o:o:o:o) main.cpp: ============================================== #include "HugeInt.hpp" #include "stdio.h" int main(int argc, char * argv) { HugeInt p("123456789" ); HugeInt q("abcdefghijklmnopqrst" ); HugeInt copie(q); HugeInt somme; HugeInt affectation; printf("p : " ); p.affiche_ascii(); printf("de taille : %i octect %i bits\n\n", p.taille, 8 * p.taille); printf("q : " ); q.affiche_ascii(); printf("de taille : %i octect %i bits\n\n", q.taille, 8 * q.taille); somme = q + p; affectation = q; printf("somme : " ); somme.affiche_ascii(); printf("de taille : %i octect %i bits\n\n", somme.taille, 8 * somme.taille); printf("copie q : " ); copie.affiche_ascii(); printf("de taille : %i octect %i bits\n\n", copie.taille, 8 * copie.taille); printf("affect q : " ); affectation.affiche_ascii(); printf("de taille : %i octect %i bits\n\n", affectation.taille, 8 * affectation.taille); //destruction p.~HugeInt(); q.~HugeInt(); somme.~HugeInt(); affectation.~HugeInt(); getchar(); return 0; } ============================================== HugeInt.hpp ============================================== //adresse basse = poids faible class HugeInt { public: char * nb ; unsigned int taille ; //constructeur-destructeur HugeInt(void) ;//grand nombre nul HugeInt(unsigned int taille ) ;//construit un grand nombre de 8*taille bits HugeInt(char * grandNombre) ;//construit un grand nombre de chaine donnée HugeInt(const HugeInt& source) ;//constructeur de copie ~HugeInt(void) ;//libere la memoire occupée //methode void affiche_chaine(void) ; void affiche_ascii(void) ; //operation HugeInt operator+(HugeInt hi) ; HugeInt operator=(HugeInt hi) ; }; ============================================== HugeIn.cpp ============================================== #include <iostream.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "HugeInt.hpp" HugeInt::HugeInt(void) { nb = NULL; taille = 0; return; } HugeInt::HugeInt(unsigned int taille) { if( (HugeInt::nb=new char[taille]) == 0) { cout << "erreur allocation memoire" << endl; exit(0); } HugeInt::taille = taille; return; } HugeInt::HugeInt(char * grandNombre) { unsigned int i,k; HugeInt::taille = k = strlen(grandNombre); if((HugeInt::nb=new char[k]) == 0) { cout << "erreur allocation memoire" << endl; exit(0); } for(i=0;i<k;i++) HugeInt::nb[i]=grandNombre[k -1 -i]; return; } HugeInt::HugeInt(const HugeInt& source) //constructeur de copie { unsigned int i; taille=source.taille; if((HugeInt::nb=new char[taille]) == 0) { cout << "erreur allocation memoire" << endl; exit(0); } for(i=0;i<taille;i++) nb[i]=source.nb[i]; return; } //destructeur HugeInt::~HugeInt(void) { if (nb != NULL) { //delete nb; //erreur ici #################################### nb=NULL; } taille=0 ; return; } void HugeInt::affiche_chaine(void) {........} void HugeInt::affiche_ascii(void) {.......} HugeInt HugeInt::operator+(HugeInt hi) { unsigned int i=0, ajout=0, retenu=0, k = 1 + (taille > hi.taille? taille : hi.taille); HugeInt resultat(k); for(i=0;i<k;i++) { ajout=retenu; if(i < taille) ajout += nb[i]; if(i < hi.taille) ajout += hi.nb[i]; resultat.nb[i] = ajout % 256 ; retenu = ajout / 256 ; } return resultat; } HugeInt HugeInt::operator=(HugeInt hi) { taille = hi.taille; delete nb; if( (nb = new char[taille]) == 0) { cout << "erreur allocation memoire" << endl; exit(0); } memcpy(nb , hi.nb , taille); return *this; } ============================================== [jfdsdjhfuetppo]--Message édité par slvn--[/jfdsdjhfuetppo] |
| slvn | :)
en effet, ce n'est pas un copier-coller de mon code :), car je ne voulais pas decourager ceux qui voulaient m aider ! mais, puisque cela semble necessaire, je vais le poster (je le poste tout de suite, enfin apres savoir comme "eviter" de creer des smileys a cause des ": o" ) en fait, ce que je cherche a recreer, c est toutes les operations normales des "int" (+ - * ^ %) mais avec des entiers de tailles quelconques :) (que je code avec des char) je cherche a faire en sorte qu il n y ait pas d instruction inutile (notement dnas les passages en parametre-reference-pointeur) et qu il n y ait pas de place de perdu (ex : a= b * c : si b est sur 10 octects et c sur 20 octect, alors a est sur 30 octects) [jfdsdjhfuetppo]--Message édité par slvn--[/jfdsdjhfuetppo] |
| LeGreg | Pendant qu'on y est ;)
Par reference(const) ou par valeur? je precise const parce que sinon y'a meme pas de question a se poser. Ben ca depend. Parfois c'est mieux de passer par reference; on s'epargne la copie de l'objet. mais parfois c'est mieux de passer par valeur; une fois l'objet copie on peut travailler dessus sans se soucier de savoir qu'il est const et sans faire de deferencement de pointeur (implicite) a chaque acces a une propriete de l'objet. A vous de voir A+ LEGREG |
| LeGreg | evidemment tu PEUX t'amuser
a changer la semantique de tous les operateurs. Par exemple que l'operateur = renvoie un objet temp const ou que l'operateur + renvoie une reference vers *this. Mais gare aux prises de tete. parce que "naturellement" tu vas te fier au comportement "presume par defaut" des operateurs mais que tu as change pour des raisons X ou Y. A+ LEGREG |
| LeGreg | ce serait bien que dans ton exemple
de code tu ne passes pas d'une notation a une autre (genre un HI qui se transforme en HugeInt) j'aurais du mal a croire que c'est juste du copier coller de ton code. une bonne idee de nous repasser l'integralite de ton code, copie-colle et sans les smileys :(. L'inconvenient des operateurs surcharges et qui est souligne dans la doc c'est que tu peux changer completement le sens des operateurs et donc rendre la comprehension du tout un peu delicate. Pour eviter les problemes il faut donc essayer le plus possible de s'en tenir a l'implantation par defaut. Quelques idees comme ca: HI &HI::operator =(const HI&); l'argument 1 est de type const pour eviter qu'il ne modifie accidentellement ton objet passe en argument. de plus il permet d'assigner depuis des objets de type const ce qui est primordial si ton argument n'est pas une lvalue !! (typiquement le resultat de a+b n'est pas une lvalue sauf si tu renvoies une reference explicitement). Le resultat est une reference vers l'objet *this (important). HI::HI(const HI&); C'est l'operateur de copie. La raison du const c'est pour la meme raison que ci dessus. Tu ne passes pas l'argument par valeur à l'operateur de Copie. Dans le cas contraire il serait oblige de s'appeler lui-meme !! Il renvoie implicitement une reference vers *this. HI HI::operator +(const HI&) const; Le premier const c'est pour la meme raison que ci-dessus. Le deuxieme const c'est pour la meme raison. (le premier argument est cache c'est *this !). Il ne renvoie pas une reference mais un objet temporaire const (important)! HI &HI::operator +=(const HI &); le const c'est pour la meme raison que les fois precedentes. L'operateur n'est pas const parce qu'il modifie l'objet courant (comme l'assignement). il ne peut donc pas operer sur des objets ou references const! (ex: (a+b)+=d; est illegal !) A+ LEGREG |
| verdoux |
|
| slvn | voici la fonction operator+
HI HI::operator+(HI &hi) { unsigned int i=0, ajout=0, retenu=0, k = 1 + (taille > hi.taille?taille:hi.taille); HI resultat(k); //construit un objet, avec nb= new char[k] et taille=k; for(i=0;i<k;i++) { ajout=retenu; if(i<taille) ajout += nb[i]; if(i<hi.taille) ajout += hi.nb[i]; resultat.nb[i] = ajout % 256 ; retenu = ajout / 256 ; } return resultat; } [jfdsdjhfuetppo]--Message édité par slvn--[/jfdsdjhfuetppo] |
| slvn | en effet c est bien la "reference" qui faisaient planter :(
bon, c est corrigé, mais ca souleve un autre problème : operator= demande un HI &hi en argument.. j avais redefinit l operateur + qui renvoyait un HI: HI HI::operator+(HI hi); et donc si j ai : HI hi1,hi2,hi3; hi1= (hi2+hi3); ne marche pu car il faudrait que hi2+hi3 soit une reference :??: c est d apres ce que me dit borland avant de compiler : [C++ Error] main.cpp(17): E2285 Could not find a match for 'HI::operator =(HI)' VCC compile, mais me fait un plantage lors de l execution .. |
| verdoux |
[jfdsdjhfuetppo]--Message édité par Verdoux--[/jfdsdjhfuetppo] |
| Kristoph | Pour le destructeur, je dirais que tu doit faire un delete [] np; parceque tu alloues un tableau et pas un simple char.
Pour l'opérateur d'affectation ( ainsi que le constructeur par recopie ), je dirais qu'il faut autant que possible passé le paramètre par reference sur un objet constant parceque le système peut utiliser ces opérateur quand tu passes un objet en paramètre à une fonction. Et puis de toute façon, c'est comme ça qu'il faut faire et pas autrement :) |
| slvn | Borland, me fait une erreur lors a la fin de l execution de mon programme:
ca se produit a cause du destructeur que j appelle moi meme : (et qui serait donc reappelé une seconde fois puisque le programme se termine) HI::~HI(void) { if (nb != NULL) {delete nb ;nb=NULL;} taille=0 ; } class HI { public: char * nb ; unsigned int taille ; HugeInt::HugeInt(int a) ; HugeIntt::~HugeInt(void) ; } HI::HI(int a) { nb = new char[a]; taille = a; } avec VCC, j ai un autre pb : quand je surcharge l operateur "=" par exemple, il plantage a l execution si le prototype de la fonction est: void HI::operator=(HI hi); mais pas si son prototype est : void HI::operator=(HI &hi); ... sachant, que je voudrais relalisé l operation : HI hi1,hi2; hi1=hi2; etant donné que ca ne va pas modifier le parametre, pkoi veut il qu on le lui passe en tant que "reference" :??: le plus curieux, c est que sous borland y a le pb du destructeur, mais pas de l operateur, et que sous vcc c est exactement l inverse... voila, je pense que ce sont pourtant des logiciels reputés ? donc c est surment moi qui ai du me planté, mais la j avoue que je capte pas.... |




