Si vous définissez en operator<<
tant que fonction membre, elle aura une syntaxe décomposée différente de celle si vous utilisiez un non-membre operator<<
. Un non-membre operator<<
est un opérateur binaire, où un membre operator<<
est un opérateur unaire.
// Declarations
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
// This is a member unary-operator, hence one argument
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
// This is a non-member binary-operator, 2 arguments
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
Alors ... comment les appelez-vous vraiment? Les opérateurs sont étranges à certains égards, je vous mets au défi d'écrire la operator<<(...)
syntaxe dans votre tête pour donner un sens aux choses.
MyObj mo;
// Calling the unary operator
mo << std::cout;
// which decomposes to...
mo.operator<<(std::cout);
Ou vous pouvez essayer d'appeler l'opérateur binaire non membre:
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
Vous n'avez aucune obligation de faire en sorte que ces opérateurs se comportent de manière intuitive lorsque vous les transformez en fonctions membres, vous pouvez définir operator<<(int)
pour déplacer à gauche une variable membre si vous le souhaitez, comprenez que les gens peuvent être un peu pris au dépourvu, quel que soit le nombre de commentaires que vous pouvez écrire.
Presque enfin, il peut y avoir des moments où les deux décompositions pour un appel d'opérateur sont valides, vous pouvez avoir des problèmes ici et nous différerons cette conversation.
Enfin, notez à quel point il peut être étrange d'écrire un opérateur membre unaire censé ressembler à un opérateur binaire (car vous pouvez rendre les opérateurs membres virtuels ..... en essayant également de ne pas dévoluer et de suivre ce chemin .... )
struct MyObj
{
// Note that we now return the ostream
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
Cette syntaxe va maintenant irriter de nombreux codeurs ...
MyObj mo;
mo << std::cout << "Words words words";
// this decomposes to...
mo.operator<<(std::cout) << "Words words words";
// ... or even further ...
operator<<(mo.operator<<(std::cout), "Words words words");
Remarquez comment le cout
deuxième argument de la chaîne est ici ... étrange, non?