OVH Cloud OVH Cloud

surcharge

14 réponses
Avatar
Nicolas Aunai
salut,


je souhaite surcharger l'opérateur '<<' afin d'afficher simplement un
objet par la ligne de code :

cout << Objet;



sachant que mon objet comprend entre autre deux tableaux, je ne vois
pas trop comment faire.


je l'ai fait pour un objet simple càd sans tableaux :

ostream &
operator<<(ostream &os, const Transition &trans)
{
os << "( depart : " << trans.depart <<", etiquette : "
<< trans.etiquette <<", arrivee : " << trans.arrivee;
return os;
}



cependant, si 'Objet' contient un tableau, il va me falloir une boucle
pour le parcourir..

qqn pourrait-il me donner un exemple ?

merci

--
Nico,
http://astrosurf.com/nicoastro
messenger : nicolas_aunai@hotmail.com

10 réponses

1 2
Avatar
Le Géant Vert
"Nicolas Aunai" ç a écrit dans le message de
news:
salut,


je souhaite surcharger l'opérateur '<<' afin d'afficher simplement un
objet par la ligne de code :
je l'ai fait pour un objet simple càd sans tableaux :

ostream &
operator<<(ostream &os, const Transition &trans)
{
os << "( depart : " << trans.depart <<", etiquette : "
<< trans.etiquette <<", arrivee : " << trans.arrivee;
return os;
}



cependant, si 'Objet' contient un tableau, il va me falloir une boucle
pour le parcourir..


la réponse est dans la question :) il te faut effectivement un parcours de
ta collection, genre, avec un vector :

en assumant :
class Obj
{
...
std::vector<super_type> data;
...
};

et l'opérateur << en friend est alors du genre :

ostream &operator <<(ostream &rOs, const Obj o)
{
std::vector<super_type>::const_iterator end = o.data.end();
for (std::vector<super_type>::const_iterator it = o.data.begin(); it ! end; ++it)
{
rOs << *it;
}
}

à condition bien sûr qu'on sache faire os << super_type :)

Avatar
Le Géant Vert
"Le Géant Vert" a écrit dans le message de
news: bqsoqf$acf$

"Nicolas Aunai" ç a écrit dans le message de
news:
salut,


je souhaite surcharger l'opérateur '<<' afin d'afficher simplement un
objet par la ligne de code :
je l'ai fait pour un objet simple càd sans tableaux :

ostream &
operator<<(ostream &os, const Transition &trans)
{
os << "( depart : " << trans.depart <<", etiquette : "
<< trans.etiquette <<", arrivee : " << trans.arrivee;
return os;
}



cependant, si 'Objet' contient un tableau, il va me falloir une boucle
pour le parcourir..


la réponse est dans la question :) il te faut effectivement un parcours de
ta collection, genre, avec un vector :

en assumant :
class Obj
{
...
std::vector<super_type> data;
...
};

et l'opérateur << en friend est alors du genre :

ostream &operator <<(ostream &rOs, const Obj o)
{
std::vector<super_type>::const_iterator end = o.data.end();
for (std::vector<super_type>::const_iterator it = o.data.begin(); it
! > end; ++it)

{
rOs << *it;
}
}

à condition bien sûr qu'on sache faire os << super_type :)




tiens, j'ai oublié un return rOs; dans le feu de l'action... :-p


Avatar
Nicolas Aunai


ostream &operator <<(ostream &rOs, const Obj o)
{
std::vector<super_type>::const_iterator end = o.data.end();
for (std::vector<super_type>::const_iterator it = o.data.begin(); it ! > end; ++it)
{
rOs << *it;
}
}

à condition bien sûr qu'on sache faire os << super_type :)



ok, mais je ne comprends pas vraiment ce qui se passe dans cette
boucle, que fait exactement :

rOs << *it; ?


hypothèse : cela place tous les éléments du vector dans le "buffer du
flux de sortie standard" est-ce exact ?

alors si j'ai plusieurs tableau je peux faire deux boucles successives
? et ainsi de suite pour chq élément de mon objet ? si j'ai bon,
existe-il une limite a ce qu'on peu ajouter a ce buffer ?

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Nicolas Aunai
que pensez-vous de mon opérateur :


ostream &
operator<<(ostream &os, Automate &a)
{
os << "Caractéristiques de l'automate :" << endl << endl;

os << "* Etats : " << endl;
os << "=========" <<endl;

for(int i=0; i < a.nb_etat; i++)
switch(a.etats[i])
{
case a.etat_initial:
os << "( etat : " << i << "type : initial )" << endl;
break;

case a.etat_intermediaire:
os << "( etat : " << i << "type : intermediaire )" << endl;
break;

case a.etat_final:
os << "(etat : " << i << "type : final )" << endl;
break;

default:
os << "(etat : " << i << "type : inconnu )" << endl;
}

os << "* Transitions :" << endl;
os << "===============" << endl;

for(int i=0; i< a.nb_trans; i++)
os << trans[i] << endl;

return os;
}

--
Nico,
http://astrosurf.com/nicoastro
messenger :
Avatar
Christophe Lephay
Nicolas Aunai wrote:
que pensez-vous de mon opérateur :


De quel point de vue ?

ostream &
operator<<(ostream &os, Automate &a)
{
os << "Caractéristiques de l'automate :" << endl << endl;

os << "* Etats : " << endl;
os << "=========" <<endl;

for(int i=0; i < a.nb_etat; i++)
switch(a.etats[i])
{
case a.etat_initial:
os << "( etat : " << i << "type : initial )" << endl;
break;

case a.etat_intermediaire:
os << "( etat : " << i << "type : intermediaire )" <<
endl; break;

case a.etat_final:
os << "(etat : " << i << "type : final )" << endl;
break;

default:
os << "(etat : " << i << "type : inconnu )" << endl;
}

os << "* Transitions :" << endl;
os << "===============" << endl;

for(int i=0; i< a.nb_trans; i++)
os << trans[i] << endl;

return os;
}


Juste une petite remarque au passage : s'il est envisageable que tu dérives
Automate, c'est mieux de faire en sorte que ton opérateur appelle des
fonctions virtuelles chargées d'en afficher le(s) état(s), par exemple :

ostream& operator<<( ostream & os, const Automate& a )
{
a.print( os ); // avec print virtuelle
return os;
}

ou alors :

ostream & operator<<(ostream &os, const Automate &a)
{
os << "Caractéristiques de l'automate :" << endl << endl;

os << "* Etats : " << endl;
os << "=========" <<endl;

a.print_etats( os ); // fonction virtuelle
a.print_transitions( os ); // re fonction re virtuelle

return os;
}

Chris

Avatar
Le Géant Vert
Juste une petite remarque au passage : s'il est envisageable que tu
dérives

Automate, c'est mieux de faire en sorte que ton opérateur appelle des
fonctions virtuelles chargées d'en afficher le(s) état(s), par exemple :


oui, je suis aussi favorable à cette idée ; le mieux c'est qu'on délègue à
chaque classe la bonne manière de s'afficher.

Avatar
Alexandre
<snip>
class Obj
{
...
std::vector<super_type> data;
...
};

et l'opérateur << en friend est alors du genre :

ostream &operator <<(ostream &rOs, const Obj o)
{
std::vector<super_type>::const_iterator end = o.data.end();
for (std::vector<super_type>::const_iterator it = o.data.begin(); it
! > end; ++it)

{
rOs << *it;
}
}

à condition bien sûr qu'on sache faire os << super_type :)


Une autre solution :

template <class Type>
class cEnvoieFlux
{
private:
ostream& flux;
public:
cEnvoieFlux(ostream& f):flux(f) {}
void operator() (const Type& T) {flux<<T;}
};

ostream &operator <<(ostream &rOs, const Obj o)
{
std::for_each(o.data.begin(),o.data.end(), cEnvoieFlux< super_type
(rOs) );
return rOs;

}

avantage : une fois le foncteur cEnvoieFlux défini, tu peux l'utiliser
chaque fois.
J'aime bien les algos génériques de la STL ;-)

Avatar
Laurent DELEPINE
Nicolas Aunai wrote:
que pensez-vous de mon opérateur :


ostream &
operator<<(ostream &os, Automate &a)
{
os << "Caractéristiques de l'automate :" << endl << endl;


Premier point : std::end, std::cout, std::ostream, etc.

os << "* Etats : " << endl;
os << "=========" <<endl;

for(int i=0; i < a.nb_etat; i++)
switch(a.etats[i])
{
case a.etat_initial:
os << "( etat : " << i << "type : initial )" << endl;
break;


Rajoute un espace avant type. Sinon le nombre va etre accolé a type
(sauf si c'est ce que tu veux.

case a.etat_intermediaire:
os << "( etat : " << i << "type : intermediaire )" << endl;
break;

case a.etat_final:
os << "(etat : " << i << "type : final )" << endl;
break;

default:
os << "(etat : " << i << "type : inconnu )" << endl;
}

os << "* Transitions :" << endl;
os << "===============" << endl;

for(int i=0; i< a.nb_trans; i++)
os << trans[i] << endl;

return os;
}


Tu as deux boucles. aussi je procederais differement. Je construirais
mes chaines dans des stringstreams dans la meme boucle et je les
enverrais en bloc apres la boucle (mais peut etre est ce du pinaillage
d'ex programmeur 3D rapide sur 486). Et naturellement les remarque de
mes collegues.


A+

LD

Avatar
Luc Hermitte
"Alexandre" wrote in news:3fd237aa$0$7162
$:

Une autre solution :

template <class Type>
class cEnvoieFlux
{ [...] };

ostream &operator <<(ostream &rOs, const Obj o)
{
std::for_each(o.data.begin(),o.data.end(), cEnvoieFlux< super_type
(rOs) );
return rOs;

}


cEnvoieFlux ~~ std::ostream_iterator

--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>


Avatar
Benoit Rousseau
Laurent DELEPINE wrote:
Tu as deux boucles. aussi je procederais differement. Je construirais
mes chaines dans des stringstreams dans la meme boucle et je les
enverrais en bloc apres la boucle (mais peut etre est ce du pinaillage
d'ex programmeur 3D rapide sur 486). Et naturellement les remarque de
mes collegues.
Quoi ? Ok, c'est Samedi soir... on boit et tout, mais bon... On essaye

de faire des phrases qui se tiennent entre elles, à défaut de phrases
non bourrées...

1 2