Question débile - fonctions membres C++ - C++ - Programmation
Marsh Posté le 10-02-2009 à 22:36:31
ton ; c'ets une erreur de frappe là ?
Sinon :
- ta methode est bien déclarée ET définie ?
montre du code complet stp
Marsh Posté le 10-02-2009 à 22:53:08
Merci pour la réponse rapide. Oui bien sûr le ; dans la définition c'est une grosse faute de frappe
Alors voilà un exemple de code complet :
Truc.h
Code :
|
Truc.cpp
Code :
|
Main.cpp
Code :
|
Diagnostic ?
Marsh Posté le 10-02-2009 à 22:55:05
c'ets quoi ton compilo
apres, detail, tes methodes devriat etre const et using namespace dans un .h merite le pal
Marsh Posté le 10-02-2009 à 22:55:30
On m'a parlé d'utiliser le pointeur this (ça m'a effectivement rappelé quelque chose), ça vous paraît une solution adaptée ? y a-t-il plus simple ? moins simple ?
Marsh Posté le 10-02-2009 à 23:02:59
normalement t'en as pas besoin à moins d'utiliser un compilo foireux.
Quel est ton compilo
Marsh Posté le 10-02-2009 à 23:06:24
Argh pardon monseigneur mais pitié pas le pal je corrige tout de suite ! pourquoi déjà au fait ? on m'a expliqué le problème que ça posait mais j'ai déjà oublié. OK pour les méthodes const, parce qu'elles ne modifient pas les attributs (right ?).
Je suis sous windaube XP avec Dev-C++ 4.9.9.2
Marsh Posté le 10-02-2009 à 23:16:07
je pense que ca n'a rien à voir mais, dev cpp ets assez moche et utilsie un vieux gcc. Installe CodeBlocks
Marsh Posté le 10-02-2009 à 23:33:38
J'avais installé CodeBlocks mais ça avait l'air moins simple à prendre en main que Dev-C++ ; cela dit si tu me dis que c'est mieux je veux bien tenter la migration.
Marsh Posté le 11-02-2009 à 00:14:48
mouletabille a écrit : J'avais installé CodeBlocks mais ça avait l'air moins simple à prendre en main que Dev-C++ ; cela dit si tu me dis que c'est mieux je veux bien tenter la migration. |
Dev-C++ est pas mal pour commencer, mais perso j'ai vite eu des emmerdes avec ... n'hésite pas à utiliser un autre IDE ...
Marsh Posté le 11-02-2009 à 01:30:35
Les gars vous me portez la poisse je viens d'avoir mes premiers ennuis avec Dev-C++ ! Problème avec l'éditeur de texte plus précisément, quand je copiais/collais des lignes ça écrasait les lignes préexistantes au lieu de les décaler vers le bas (pourtant je n'étais pas en mode "inser" au niveau du clavier) et après impossible de sélectionner des portions de lignes, seulement des lignes entières ; ça vous parle ? Bon en tous cas je vais suivre vos conseils et me mettre à CodeBlocks asap.
Sinon, il semble effectivement que le pointeur "this" qui pointe sur l'objet courant soit la solution à mon problème ; en l'occurrence, pour ceux que ça intéresse, on a les deux possibilités équivalentes :
Code :
|
ou
Code :
|
La voilà l'utilité de ce fameux pointeur ! (elle n'est pas évidente à première vue lorsqu'on lit un cours de C++)
Bon je risque fort d'avoir d'autres questions dans les jours prochains alors à très bientôt !
Marsh Posté le 11-02-2009 à 07:31:05
sauf que non, tu n'en as pas besoin normalement si l'appel est non-ambigu ....
Marsh Posté le 11-02-2009 à 17:47:58
Ecoute vu que j'ai corrigé pas mal de bugs entre temps, peut-être qu'en fait ce n'était pas ça le problème. Je toujours essayer d'enlever le this pour voir si ça fonctionne encore ?
Autre question, du même niveau : j'ai une classe Point par exemple, et une classe Cercle qui a comme attributs :
Code :
|
Comment écrire le constructeur par défaut de Cercle, sachant que je veux qu'il appelle le constructeur par défaut de la classe Point ? Est-ce que c'est
Code :
|
? ou est-ce plus subtil ?
Merci d'avance.
Marsh Posté le 11-02-2009 à 17:56:06
Si tu veux
Code :
|
suffit. Mais tu peux etre explicite avec
Code :
|
Marsh Posté le 11-02-2009 à 18:03:36
Super merci beaucoup à vous deux ! C'est mieux d'utiliser une liste d'initialisation donc ?
Et si maintenant je veux surcharger le constructeur pour mettre un point en paramètre je fais :
Code :
|
vrai ?
Marsh Posté le 11-02-2009 à 18:04:37
oui sauf que Point serait à passer en reference constante :
Code :
|
pr eviter des copies inutiles
Marsh Posté le 11-02-2009 à 18:09:45
OK, et donc aussi dans mon prototype je suppose ?
Code :
|
Et si ensuite j'ai une méthode de Cercle qui modifie le centré (via des méthodes Point::set_x(double nouveau_x) ) ce n'est pas gênant d'avoir mis un const ?
Marsh Posté le 11-02-2009 à 18:14:22
..et pour l'appel du coup je fais
Code :
|
ou bien
Code :
|
ou encore autre chose ?
Désolé de vous embêter hein
Marsh Posté le 11-02-2009 à 19:07:58
Non, tu passes jsute tona rguemnt de manière constante, puis tu en fais une copie. La copie elle n'est pas constante.
Pour l'appelle Cercle c(pt) suffit, car référence != pointeur
Marsh Posté le 11-02-2009 à 19:23:48
C'est bien ça le problème. J'avais bien compris (enfin je crois) les pointeurs, mais les références ça m'embrouille tout dans mes petits neurones. Si je comprends bien :
- le passage par référence sert à éviter une copie inutile de l'argument ;
- mais du coup cet argument risquerait d'être modifié, donc on met const pour l'empêcher ?
Pour résumer, je mets :
- dans le prototype :
Code :
|
- dans la définition :
Code :
|
- dans l'appel :
Code :
|
Right ?
Marsh Posté le 11-02-2009 à 19:37:19
Presque :
- dans le prototype :
Code :
|
- dans la définition :
Code :
|
- dans l'appel :
Code :
|
Marsh Posté le 11-02-2009 à 19:49:10
En effet ! D'ailleurs mon compilo n'a pas manqué de m'insulter quand j'ai essayé d'enlever le const& dans le prototype Et puis entre-temps j'ai relu la petite fiche que je m'étais faite sur les références, ça commence à se ré-éclaircir.
Merci encore en tous cas pour toute ton aide, tu me fais gagner un temps précieux ! A très bientôt pour de nouvelles questions (ce soir sans doute)
Marsh Posté le 12-02-2009 à 16:01:29
Comme promis je reviens avec deux nouvelles questions. Je précise que j'ai déjà trouvé des solutions via des recherches sur le net mais je ne suis pas sûr qu'elles soient optimales.
J'explique mon problème ; j'ai un objet de ma classe Cercle (et plus tard d'autres classes géométriques) et je voudrais connaître quelles sont les valeurs possibles pour l'abscisse d'un point de mon cercle. La réponse est un intervalle, donc j'ai créé un classe intervalle dont voici la déclaration (je vous laisse deviner l'implémentation) :
Code :
|
La méthode "afficher" renvoie une chaîne de caractères "[ a ; b ]" où a=centre-rayon et b=centre+rayon sont les bornes de l'intervalle. Premier problème : la concaténation des string avec l'opérateur + ne marche pas avec des doubles, c'est-à-dire qu'en écrivant :
Code :
|
je me fais insulter par le compilo. Donc il faut convertir les double en string --> solution trouvée sur un forum anglophone, utiliser un flux, donc un #include<sstream> et dans ma méthode :
Code :
|
Mais ça me paraît un peu compliqué, auriez-vous plus simple ?
Deuxième problème : dans la classe Cercle je veux créer ma méthode qui renvoie l'Intervalle des abscisses, et là problème.. je ne sais pas comment mettre un objet comme valeur de retour ! Enfin dans le prototype OK c'est facile je fais :
Code :
|
mais dans l'implémentation je ne sais pas quoi mettre en return... C'est débile non ? Entre temps j'ai trouvé une solution grâce à mes réivsions sur les références (merci Joel F) : passer un Intervalle par référence, donc ma fonction devient :
Code :
|
et dans la fonction je fais du
Code :
|
etc. Mais quelle est la bonne méthode ?
Merci !
Marsh Posté le 12-02-2009 à 18:05:14
Q1/ non c'est la bonne manière.
Q2/ t'as le choix :
- soit ut fais untruc avec une reference pr la sortie et tu fais comemù tu dis
- soit tu construit un objet à renvoyer :
Code :
|
Par contre ça implique que Intervalle satisfasse la Forme Canonique de Coplien (je te laisse te renseigner la dessu). De même je pense qu'il serait plus judicieux que intervalle ets un constructeur qui prenne cercle et rayon et qui l'initialise.
Tu pourrais alors faire :
Code :
|
Marsh Posté le 13-02-2009 à 01:40:50
Merci pour ta réponse. J'ai fait une petite recherche sur la forme canonique de Coplien, je vois à peu près ce que c'est (justement je suis en plein dans la surcharge des opérateurs).
Pas de problème pour fournir systématiquement le constructeur par copie et l'opérateur = s'il le faut, mais pour le destructeur j'ai un petit doute ; pour des objets simples comme les miens, il n'y a rien à implémenter non ? Il n'y a pas d'allocation dynamique ni de pointeurs... Du coup dans Intervalle.cpp j'écris juste, dis-moi si je délire :
Code :
|
En effet tu as raison il est plus simple de faire directement un constructeur surchargé plutôt que d'utiliser les accesseurs.
Merci pour la confirmation pour ma Q1, du coup on peut faire un point plus simple :
Code :
|
Marsh Posté le 15-02-2009 à 19:14:07
Salut tout le monde,
Alors pour commencer je uppe ma question sur le destructeur, dans le cas de classes très simples.
Ensuite voilà une nouvelle question : j'ai une classe Point, avec deux attributs double m_x et double m_y. J'ai surchargé l'opérateur d'affectation, et les opérateurs +,-,* en écrivant :
Code :
|
idem pour le -, pour le * c'est le produit scalaire :
Code :
|
et il y aussi la multiplication par un double :
Code :
|
Jusqu'ici tout va bien.
Ensuite j'ai une classe Triangle, qui a trois attributs : Point m_A, Point m_B, Point m_C. Je veux écrire une méthode barycentre, qui donne simplement (m_A + m_B + m_C) / 3, donc j'écris :
Code :
|
Et là big problem : le compilateur m'envoie
"In member function 'Point Triangle::barycentre() const':
passing 'const Point' as 'this' argument of 'Point Point::operator+(const Point& )' discards qualifier"
Kézako ? J'ai trouvé une solution de rechange en écrivant
Code :
|
(en utilisant le constructeur surchargé Point(double x, double y) et les accesseurs) mais je trouve ça dommage de ne pas pouvoir utiliser mes opérateurs surchargés...
Merci d'avance pour vos éclaircissements !
Marsh Posté le 15-02-2009 à 20:30:32
les operateurs symmétriques comme + doivent etre implanté comme fonction libre non-friend et non comme membre. Mieux, la fonction + doit etre implanté à partir de la méthode +=
Code :
|
Marsh Posté le 15-02-2009 à 21:24:13
Ah ah alors ça je ne l'aurais pas trouvé tout seul. C'est cool ! Et ça me plait plus une définition symétrique comme ça. J'en apprends tous les jours avec toi mon cher Joel F.
Et pour la multiplication (Point * double) je mets une fonction "hors-classe" aussi ?
Marsh Posté le 15-02-2009 à 22:00:21
Autre question : pourquoi le type de retour de la méthode est-il Point& et pas Point ? (*this) désigne bien l'objet lui-même non ?
Marsh Posté le 15-02-2009 à 22:26:29
en general, les fonctions symmetriques sont externes oui.
Pour +=, bah += c'ets + et = et = renvoit this pr pouvoir chainer :
a= p += q+r;
Marsh Posté le 15-02-2009 à 22:43:57
OK je note. Cela dit Point * double n'est pas symétrique (et j'en ai d'autres comme ça, Matrice * double, Matrice * point...)
En fait j'ai du mal à comprendre le coup du Point&.
Perso, puisque += écrase les anciennes valeurs des attributs, intuitivement j'aurais défini ça comme une méthode void :
Code :
|
Non ? Et d'ailleurs est-ce qu'il vaut mieux utiliser les méthodes get pour accéder aux attributs de l'autre objet, même si on reste dans la classe ?
Marsh Posté le 15-02-2009 à 22:49:56
non, toutes les variantes de = doivent renvoyer l'objet modifier pr le chainage :
a = b =c;
ou a += b += d;
pr Point*double, tu oublies que double*Point est semantiquement identique, elle ets donc symetrique.
Marsh Posté le 15-02-2009 à 22:59:38
OK je comprends mieux. Mais (désolé d'être lourd) le type de l'objet est Point tout court ; je ne comprends pas pourquoi le type de retour de la fonction est Point& ? On renvoie le point et pas une référence sur le point...
D'accord pour la symétrie, pour moi ça ne coulait pas de source car je voyais ça comme une méthode
Code :
|
du coup le point est forcément le premier opérande et on ne peut pas écrire double * Point. Alors que si on le met en fonction libre on peut définir les deux fonctions :
Code :
|
Code :
|
Marsh Posté le 15-02-2009 à 23:04:53
bah si = ou += renvoyait une instance, il faudrait la recopier depuis la pile vers sa destination, ce qui serait bien couteux.
Marsh Posté le 15-02-2009 à 23:17:40
Ouaip je vois à peu près... Bon il faut que je médite tout ça.
Je commence par modifier mon code suivant tes conseils et je te raconte ce que ça donne.
Marsh Posté le 15-02-2009 à 23:44:07
Par contre l'opérateur d'affectation = je le laisse comme membre de la classe (because forme canonique de Coplien etc.) ou alors non (because égalités chaînées) ?
Marsh Posté le 15-02-2009 à 23:52:59
En fait l'histoire de renvoyer une référence plutôt qu'une instance ça vaut pour n'importe quelle fonction renvoyant un objet non ?
Après promis j'arrête de te submerger de questions.
Marsh Posté le 16-02-2009 à 07:28:41
operator= n'est pas symetrique car le membre gauche à un role particulier :=> membre
Pour le retour de référence, ca ne vaut que si tu veut chainer tes appels sur un meme objet initial. Sinon tu renvois une instance vu que tu n'as pas le droit de renvoyer une reference sur un objet temporaire.
Marsh Posté le 18-02-2009 à 00:36:01
Yo,
Bon ça marche très bien en mettant les =,+=, etc."in-class" et led +,-,*, "out-class". Et en fait renvoyer un Objet ou un Objet& ne change pas trop le fonctionnement (du mons pour l'usage que j'en fais, pas d'affectations en chaîne).
Marsh Posté le 10-02-2009 à 22:24:37
Salut à tous,
Attention ma question va sans doute paraître très très basique à certains mais pitié ne vous moquez pas Je précise dabord que j'ai bien sûr commencé par fair une recherche sur le forum, et dans le divers tutos que j'ai l'habitude de consulter en tant que grand débutant en C++, mais en vain. Je pense que c'est trop facile pour être mentionné !
Donc voilà j'en viens au fait : j'ai défini une classe Truc, avec une fonction membre Func1 :
Maintenant je veux définir une autre méthode dans la même classe, qui utilise le résultat de la précédente, par exemple je veux calculer son carré ; j'ai essayé
Mais ça n'a pas l'air de fonctionner. Quelle est la bonne manière de le faire ?
Merci d'avance pour votre réponse (et votre indulgence ).