Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

probleme fonction friend

7 réponses
Avatar
YaNn
salut :)


Voici la classe avec laquelle j'ai un problème lors
de la compilation :

la classe Point3D definie une fonction friend qui permet de
renvoyer un Vecteur en surchargeant l'operateur -

#ifndef _POINT3D_HPP_
#define _POINT3D_HPP_

#include <iostream>

#include "Vecteur.hpp"

using namespace std;

class Point3D
{

public :

// Attributs publiques

double X; // coordonn?e en X
double Y; // coordonn?e en Y
double Z; // coordonn?e en Z

// Constructeurs

Point3D(); // defaut
Point3D(const Point3D &p); // copie
Point3D(double x, double y, double z);

// Fonction Friend

friend Vecteur operator-(const Point3D &a, const Point3D &b);

// Surcharge des op?rateurs

friend ostream &operator<<(ostream &os, Point3D &p);

}; // Point3D

#endif

lorsque je compile, le compilateur me dit que je n'ai pas le droit
de definir Vecteur sans type de retour et ne veut rien me compiler.
J'ai bien compris qu'il interpretait Vecteur comme le nom de la fonction
mais je ne vois pas pourquoi :(

Si quelqu'un à déjà eu se problème, je veux bien une explication car
meme dans la "bible" de stroustrup, c'est autorisé :)

7 réponses

Avatar
Ivan Vecerina
"YaNn" wrote in message
news:bq0iiq$rfq$
| Voici la classe avec laquelle j'ai un problème lors
| de la compilation :
|
| la classe Point3D definie une fonction friend qui permet de
| renvoyer un Vecteur en surchargeant l'operateur -
....
| #include "Vecteur.hpp"
Je suspecte un problème avec ce fichier, que tu n'as pas inclus.
Si je remplace simplement la ligne précédente avec:
class Vecteur; // forward-declaration
... le reste du code que tu a fourni compile sans erreur.

Se pourrait-il que Vecteur soit caché à l'intérieur d'un namespace?

| class Point3D
| {
...
| friend Vecteur operator-(const Point3D &a, const Point3D &b);
...
| }; // Point3D
...
| lorsque je compile, le compilateur me dit que je n'ai pas le droit
| de definir Vecteur sans type de retour et ne veut rien me compiler.
| J'ai bien compris qu'il interpretait Vecteur comme le nom de la fonction
| mais je ne vois pas pourquoi :(
Je pense que c'est parce que le type Vecteur n'est pas visible
par le compilo...


Amicalement,
Ivan
--
http://ivan.vecerina.com
Avatar
Benoit Rousseau
Ivan Vecerina wrote:
"YaNn" wrote in message
news:bq0iiq$rfq$
| Voici la classe avec laquelle j'ai un problème lors
| de la compilation :
|
| la classe Point3D definie une fonction friend qui permet de
| renvoyer un Vecteur en surchargeant l'operateur -
....
| #include "Vecteur.hpp"

Je suspecte un problème avec ce fichier, que tu n'as pas inclus.
Si je remplace simplement la ligne précédente avec:
class Vecteur; // forward-declaration
... le reste du code que tu a fourni compile sans erreur.


Je pense que c'est la solution (class Vecteur;), mais que le problème
vient des conditions de préprocesseurs...
A mon avis, Vecteur.hpp inclue à son tour Point.hpp et à cause des
protections avec #ifndef #define Vecteur ne voit pas Point quand il est
appelé et vis et versa.




--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
YaNn
Benoit Rousseau wrote:
Ivan Vecerina wrote:

"YaNn" wrote in message
news:bq0iiq$rfq$
| Voici la classe avec laquelle j'ai un problème lors
| de la compilation :
|
| la classe Point3D definie une fonction friend qui permet de
| renvoyer un Vecteur en surchargeant l'operateur -
....
| #include "Vecteur.hpp"



Je suspecte un problème avec ce fichier, que tu n'as pas inclus.
Si je remplace simplement la ligne précédente avec:
class Vecteur; // forward-declaration
... le reste du code que tu a fourni compile sans erreur.



Je pense que c'est la solution (class Vecteur;), mais que le problème
vient des conditions de préprocesseurs...
A mon avis, Vecteur.hpp inclue à son tour Point.hpp et à cause des
protections avec #ifndef #define Vecteur ne voit pas Point quand il est
appelé et vis et versa.






Effectivement la classe Vecteur importe la classe Point3D, bien vu :)

Je vais donc faire une forward declaration pour que cela passe, merci
beaucoup :)


Avatar
YaNn
Effectivement, la compilation se déroule presque sans problème maintenant :)

voici le code de ma surcharge de l'opérateur - :

Vecteur &operator-(const Point3D &a, const Point3D &b)
{
Vecteur v(b.X-a.X, b.Y-a.Y, b.Z-a.Z);
return v;
}

je pensais que cela marcherait mais il reste quand même un warning :

warning: reference to local variable `v' returned

Quelle est la meilleures solution à ce problème ?

Dois-je renvoyer seulement un Vecteur (j'ai essayé, cela marche mais je
ne sais pas pourquoi cela me gène) ou un Vecteur * ?
Avatar
Alexandre

voici le code de ma surcharge de l'opérateur - :

Vecteur &operator-(const Point3D &a, const Point3D &b)
{
Vecteur v(b.X-a.X, b.Y-a.Y, b.Z-a.Z);
return v;
}

je pensais que cela marcherait mais il reste quand même un warning :


Et pour cause !!


warning: reference to local variable `v' returned

Quelle est la meilleures solution à ce problème ?


Le compilo te prévient, gentiment d'ailleurs, que ton code va planter. En
fait, tu renvoies une référence sur un vecteur qui n'existera plus quand ta
fonction sera terminée. ton 'v' est une variable locale, donc sera dépilée à
la fin de l'appel. Or tu la renvoies par référence.. grosso modo tu
transmets son adresse, quoi. C'est qq chose de non valide après l'appel. A
ne pas faire.
La seule solution simple est de renvoyer PAR VALEUR et non par référence.
Vecteur operator-(const Point3D &a, const Point3D &b)
{
Vecteur v(b.X-a.X, b.Y-a.Y, b.Z-a.Z);
return v;
}

Dois-je renvoyer seulement un Vecteur (j'ai essayé, cela marche mais je
ne sais pas pourquoi cela me gène) ou un Vecteur * ?
Un vecteur simple, comme je viens de l'écrire. Tu aurais les mêmes problèmes

avec un Vecteur*.

A+

Avatar
Loïc Joly
YaNn wrote:

Effectivement, la compilation se déroule presque sans problème
maintenant :)

voici le code de ma surcharge de l'opérateur - :

Vecteur &operator-(const Point3D &a, const Point3D &b)
{
Vecteur v(b.X-a.X, b.Y-a.Y, b.Z-a.Z);
return v;
}

je pensais que cela marcherait mais il reste quand même un warning :

warning: reference to local variable `v' returned


C'est en fait un comportement indéfini dans ton code. Tu retournes une
référence à un objet local, qui sera donc détruit à la fin de la
fonction, et donc avant que celui qui appèle ta fonction ne puisse faire
quelquechose de ta référence. Dès qu'il va y toucher, to programme peut
faire BOUM.


Quelle est la meilleures solution à ce problème ?

Dois-je renvoyer seulement un Vecteur (j'ai essayé, cela marche mais je
ne sais pas pourquoi cela me gène) ou un Vecteur * ?


Retourner un pointeur est très lourd. Par exemple, pour faire a = b-c-d,
si ton opérateur retourne un pointeur, tu vas obligé l'utilisateur à
écrire :
Vecteur *a1 = b-c;
Vecteur *a2 = (*a1)-d;
a = *a2;
delete a1;
delete a2;

Pas génial, n'est-ce pas ?

Donc, à part quelques autre tentatives elles aussi vouées à l'échec
(retourner une référence à une variable statique,...) il ne reste que
deux bonnes solution : Retourner un vecteur diretement, ou alors partir
sur une optique de fonction qui prend une référence en entrée et la modifie.

Le problème du retour par valeur est qu'il a potentiellement un impact
sur les performances mais la RVO (return value optimisation) permet de
s'en sortir (reste qu'il peut être intéressant de savoir si ton
compilateur l'implémente, et si oui s'il y a des façon d'écrire le code
qui l'aide à l'utiliser).

--
Loïc

Avatar
YaNn
Merci :)

J'ai opté pour la solution friend Vecteur operator-(Point3D &, Point3D
&). Merci pour vos explications qui clarifient grandement les choses.

Je posterai un lien pour voir mon système physique lorsque j'aurai fini :)

ps : je me documente sur la RVO :)