Entrees/sorties c++

Résolu/Fermé
Asterix2231 Messages postés 50 Date d'inscription mardi 5 février 2008 Statut Membre Dernière intervention 16 avril 2013 - 14 janv. 2010 à 10:30
Asterix2231 Messages postés 50 Date d'inscription mardi 5 février 2008 Statut Membre Dernière intervention 16 avril 2013 - 15 janv. 2010 à 19:56
Bonjour,

J'ai créé pour un programme une classe Vecteur dans un fichier vecteur.h comme ceci:

class Vecteur{
public:
double x,y,z;
};

Ainsi qu'une classe Grain dans un fichier grain.h:

#include vecteur.h

Class Grain{
private:
Vecteur pos;
};

L'idée étant que la position du centre d'un grain soit décrite par un vecteur.


Afin de pouvoir afficher simplement les coordonnées d'un vecteur à l'écran par l'appel de "cout << V;" (où V est de type Vecteur), j'ai décidé de surcharger l'opérateur << dans le fichier vecteur.cpp:

ostream& operator<<(ostream& sortie, Vecteur& V){
return sortie << V.x << "\t" << V.y << "\t" << V.z;
}

De même je veux pouvoir afficher simplement les coordonnées du centre d'un grain grâce à la commande "cout << G;" où G est un objet de type Grain.
J'écris donc la surcharge (mise en amie dans la classe Grain) dans le fichier grain.cpp:

ostream& operator<<(ostream& sortie, Grain& G){
return sortie << G.pos;
}


Avec ce code, g++ me dit qu'il ne trouve pas de correspondance pour l'appel de l'opérateur << :

grain.cc: In function «std::ostream& operator<<(std::ostream&, Grain&)»:
grain.cc:101: erreur: no match for «operator<<» in «sortie << G->Grain::_pos»


Je précise que tous mes fichiers sont dans le même dossier, et que j'ai d'autres fonctions dans ma classe Grain qui appellent des fonctions de la classe vecteur, et que celles ci fonctionnent; ça ne semble donc pas être un problème d' inclusion de fichier.

Quelqu'un aurait une idée de ce que je fais mal? Je ne suis pas très performant concernant les entrées/sorties...

10 réponses

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
14 janv. 2010 à 11:13
J'ai repris ton code, et j'ai eu la même erreur. Voici le message complet :

In function `std::ostream& operator<<(std::ostream&, Grain&)': 
no match for 'operator<<' in 'sortie << (+g)->Grain::getPos()' 
candidates are: (...)
                std::ostream& operator<<(std::ostream&, Vecteur&) 
                std::ostream& operator<<(std::ostream&, Grain&)

Cette erreur se résout comme ceci : enlève le & dans ton paramètre de operator<<

std::ostream& operator<<(std::ostream& sortie, Vecteur v)
std::ostream& operator<<(std::ostream& sortie, Grain g)

Ça devrait mieux marcher, à moins qu'il y ait une erreur ailleurs ;-)
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
14 janv. 2010 à 12:48
déjà, pos est privée, mais l'erreur ne concorde pas...
Le fait d'enlever les références n'est pas une bonne solution. J'essayerai d'abord en mettant const devant.
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
14 janv. 2010 à 14:35
Dans la classe 'Vecteur', la déclaration doit être:
friend ostream& operator<<(ostream& ostr, const Vecteur& v)
{
  ostr << v.x << " " << v.y  << " " << v.z;
  return (ostr);
}
Bonne continuation?
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
14 janv. 2010 à 14:38
je crois que ce n'est pas très ISO la déclaration de fonction dans une classe. Gcc 4 refuse en tout cas.
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148 > Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023
14 janv. 2010 à 14:47
Je viens d'essayer avec un 4.4 et il ne dit rien. Mais peu importe, tu déclares le prototype dans la classe (il le faut bien pour que les fonctions aient accès aux membres privés de la classe) et tu explicites la fonction à l'extérieur.
Pour la question de l'ISO, je ne sais pas.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297 > loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017
14 janv. 2010 à 15:41
non, bien sur, mais déclaration plus codage : là il y a un problème. Nous avons eu le souci, mais je ne sais plus exactement quand il se produisait.
Pour le friend, c'est pas la peine car x y z sont des membres public de Vecteur. Par contre pas pos de Grain
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
14 janv. 2010 à 14:45
Je suis d'accord avec Char Snipeur, il faudrait mettre la déclaration éventuellement dans le fichier Vecteur.cpp mais en tout cas pas dans la définition de la classe.

Mais c'est vrai que comme rappelé par loupius, il manque friend dans la déclaration d'Asterix223, même si je ne comprends pas comment ça a pu marcher sans...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Asterix2231 Messages postés 50 Date d'inscription mardi 5 février 2008 Statut Membre Dernière intervention 16 avril 2013 11
14 janv. 2010 à 16:22
Bonjour,

Merci pour vos réponses.

Comme je l'ai (mal?) expliqué dans mon post, ma fonction est déclarée friend dans ma classe Grain (fichier grain.h), et implémentée dans un autre fichier (grain.cpp). Elle devrait normalement avoir accès aux données privée de la classe Grain.

De plus comme l'a justement remarqué Char Snipeur, les données de la classe Vecteur sont toues publiques, donc accessibles.

Je viens d'essayer en ajoutant "const" (dans le .h et le .cpp):

ostream& operator<<(ostream& sortie, const Grain& G);

mais rien n'y fait, j'ai la même erreur.


D'autres idées? Ou j'abandonne l'idée de vouloir à tout pris faire deux fonctions et n'en utilise q'une du type:

friend ostream& operator<<(ostream& sortie, Grain G);

ostream& operator<<(ostream& sortie, Grain G){
return sortie << Grain._pos.x << Grain._pos.y << Grain._pos.z;
}

(ce qui compile, soit dit en passant)?
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
14 janv. 2010 à 17:05
Je ne sais pas si mon exemple répond à ta demande, car j'ai bien du mal à comprendre ce que tu veux vraiment. Pardonne-moi si je n'ai pas su interpréter tes explications.
#include <iostream>
#include <cstdlib>
using namespace std;

class Vecteur
{
  public:
    Vecteur (int x0, int y0, int z0) : x(x0), y(y0), z(z0) {}
  private:
    int x, y, z;
    friend ostream& operator<<(ostream& sortie, Vecteur& V);
};

ostream& operator<<(ostream& sortie, Vecteur& V)
{
  cout << "(" << V.x << ", " << V.y << ", " << V.z << ")";
  return sortie;
}

class Grain
{
  public:
    Grain(int x, int y, int z) { pos = new Vecteur(x, y, z); }
    ~Grain() { delete pos; }
  private:
    Vecteur* pos;
    friend ostream& operator<<(ostream& sortie, Grain& G);
};

ostream& operator<<(ostream& sortie, Grain& G)
{
  cout << "grain=" << *G.pos << endl;
  return sortie;
}

int main(int argc, char *argv[])
{
  Grain grain(1, 2, 3);
  cout << grain;
  return EXIT_SUCCESS;
}

[loupius@p3000]$ g++ -Wall essai.cpp
[loupius@p3000]$ ./a.out
grain=(1, 2, 3)
[loupius@p3000]$
Nota: Avec mon compilateur (gcc 4.4.2), la compilation s'effectue très bien avec les fonctions dans les classes.
Bonne continuation.
0
Asterix2231 Messages postés 50 Date d'inscription mardi 5 février 2008 Statut Membre Dernière intervention 16 avril 2013 11
14 janv. 2010 à 23:24
Merci d'avoir passé un peu de temps sur mon problème.

Ce que je veux c'est surcharger l'opérateur << pour pouvoir écrire "cout << V;" et "cout << G" (où V est un vecteur et G est un grain) dans mon main et que cela m'affiche les cordonnées soit du vecteur, soir du centre du grain.

Comme je défini la position du centre du grain par un vecteur, j'ai pensé que la surcharge:
ostream& operator<<(ostream& sortie, Grain G){
...
}

pourrait appeler
ostream& operator<<(ostream& ostr, Vecteur V){
...
}

Maintenant avec le code que tu me donnes je suis d'accord, ca tourne. Seulement puisque tu affiches les coordonnées avec cout dans l'implémentation des deux fonctions qui nous intéressent, je ne vois plus trop l'utilité de retourner un flux (return sortie;) qui, dans ma tête, n'a pas changé au cours de la fonction... Ca je ne sais pas si c'est super clair :p


En tout cas merci, ca m'ira bien pour le moment, je vais potasser ça tranquillement.

Au revoir.
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
14 janv. 2010 à 23:51
La surchage d'un opérateur d'une classe impose de retourner le type de la classe, il n'y a pas à discuter.
Mais en plus cela permet d'enchaîner les opérations.
Bonne continuation.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
15 janv. 2010 à 09:44
La surchage d'un opérateur d'une classe impose de retourner le type de la classe, il n'y a pas à discuter.
je ne suis pas sur de comprendre...
Moi, j'aurai plutôt écris, mais je me trompe peut être :
ostream& operator<<(ostream& sortie, Grain& G)
{
  sortie << "grain=" << *G.pos << endl;
  return sortie;
}
de cette façon on peut aussi écrire dans un fichier par exemple, non ?
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148
15 janv. 2010 à 14:10
Oui bien sûr, il faut mettre 'sortie << ...' (Voir post n° 4). J'ai fait une erreur en recopiant un essai.
C'est sans doute cette erreur qui a fait dire à Astérix :'je ne vois plus trop l'utilité de retourner un flux'; il a raison de se poser la question mais la réponse est que de toutes façons on ne peut pas y couper: il faut retourner le type de la classe dont on a surchargé l'opérateur.
Bonne journée.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
15 janv. 2010 à 14:29
il faut retourner le type de la classe dont on a surchargé l'opérateur
Soit je ne comprends pas ce que tu veux dire, soit j'ai des lacune.
par exemple, toi tu écrirais :
A A::operator double(){}
0
loupius Messages postés 697 Date d'inscription dimanche 1 novembre 2009 Statut Membre Dernière intervention 31 décembre 2017 148 > Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023
15 janv. 2010 à 15:23
Il n'est effectivement pas obligatoire de retourner le type de la classe.
Je restais bloqué sur les opérateurs classiques avec lesquels je n'arrive pas à trouver un exemple où il n'est pas retourné un type de la classe. Par contre, je surchage souvent l'opérateur '[]' pour contrôler les débordements et effectivement (et évidemment) on ne retourne pas le type de la classe.
Quant aux opérateurs de conversion, je n'en ai jamais utilisé.
Merci de m'avoir sorti de mon erreur.
0
Asterix2231 Messages postés 50 Date d'inscription mardi 5 février 2008 Statut Membre Dernière intervention 16 avril 2013 11
15 janv. 2010 à 17:34
Bonjour,

En effet c'est ce qui m'a fait me questionner sur l'utilité de retourner un flux. Cependant je suis d'accord que par définition la surcharge, au moins de l'opérateur <<, nécessite de retourner un type ostream& pour l'usage que je veux en faire.

Par contre viens d'écrire ces lignes de codes pour tester, et il se trouve que ca fonctionne parfaitement:

vecteur.h
class Vecteur{
public:
double x,y,z;
Vecteur(double x0=0,double y0=0,double z0=0);
friend ostream& operator<<(ostream& ostr, Vecteur& V);
};

vecteur.cc
Vecteur::Vecteur(double x0, double y0, double z0){
x=x0;
y=y0;
z=z0;
}

ostream& operator<<(ostream& ostr, Vecteur& V){
ostr << V.x << " " << V.y << " " << V.z;
return ostr;
}


grain.h
class Grain{
Vecteur pos;

public:
Grain(double x0, double y,double z0);
friend ostream& operator<<(ostream& ostr, Grain& G);
};

grain.cc
Grain::Grain(double x0, double y0, double z0){
pos.x = x0;
pos.y = y0;
pos.z = z0;
}

ostream& operator<<(ostream& ostr, Grain& G){
ostr << G.pos;
return ostr;
}

main.cc
int main(){
Grain G(1,2,3);
cout << G << endl;
}


Ce qui en réalité correspond à ce que je souhaite faire depuis le début. Je dois avoir d'autres erreurs cachées les classes grain et vecteur initiales, qui sont plus grosses que ce que j'ai posté au début, et qui génèrent tout le blabla de mon compilateur.

Je vais regarder tout ça. Merci de vous êre penchés là dessus!

Bonne soirée.
0
Asterix2231 Messages postés 50 Date d'inscription mardi 5 février 2008 Statut Membre Dernière intervention 16 avril 2013 11
15 janv. 2010 à 19:56
Ce qui change en réalité, c'est que j'ai déclaré le prototype:

ostream& opérator<< (ostream& ostr, Vecteur V);

comme friend dans la classe vecteur.h, et là ça fonctionne. Je ne comprends cependant pas pourquoi c'est nécessaire, étant donné que toutes les données de cette classe sont publiques.

Au revoir.
0