std::cout
est une instance de std::ostream
. std::cout << "something"
appelle l'un des operator<<
surcharges comme cela serait fait pour toute instance de std::ostream
.
Elle est "spéciale" dans la mesure où elle fait référence à la console, mais sinon elle se comporte exactement comme une ofstream
ou un ostringstream
serait.
EDIT : Le chaînage fonctionne comme pour tous les autres opérateurs. Considérez :
class MyType
{
friend std::ostream& operator<<(std::ostream& target, const MyType& source);
int val;
public:
MyType()
: val(0)
{ }
MyType& Add(int toAdd)
{
val += toAdd;
return *this;
}
};
MyType& operator+(MyType& target, int toAdd)
{
return target.Add(toAdd);
}
std::ostream& operator<<(std::ostream& target, const MyType& source)
{
target << source.val;
return target; //Make chaining work
}
int main()
{
MyType value1;
value1 + 2 + 3 + 4;
std::cout << value1 << " and done!" << std::endl;
}
Dans ce cas, le chaînage pour +s sur MyType
fonctionnent pour la même raison que les <<
en plus du travail de l std::ostream
. Les deux sites +
y <<
sont associatifs à gauche, ce qui signifie qu'ils sont évalués de gauche à droite. Dans le cas des opérateurs surchargés, l'opérateur est remplacé par l'appel de fonction équivalent.
EDIT2 : Un peu plus en détail :
Disons que tu es le compilateur et que tu analyses les données.
std::cout << value1 << " and done!" << std::endl;
D'abord, <<
est associatif à gauche, donc on commence à gauche. Vous évaluez le premier <<
et le transformer en appel de fonction :
operator<<(std::cout, value1) << " and done!" << std::endl;
Vous voyez alors que vous avez à nouveau un std::ostream
(le résultat de l'appel à operator<<
), et un char *
que vous transformez à nouveau en appel de fonction :
operator<<(operator<<(std::cout, value1)," and done!") << std::endl;
et ainsi de suite jusqu'à ce que vous ayez traité l'ensemble de la déclaration.
0 votes
Si vous voulez vraiment tout savoir sur iostreams, vous pouvez jeter un coup d'œil à une copie de amazon.com/Standard-IOStreams-Locales-Programmers-Reference/dp/
18 votes
El
cout <<
ycin >>
Les expressions sont les raisons pour lesquelles le C++ est si peu intuitif et difficile à apprendre.17 votes
@Mehrdad : Si vous choisissez un langage en fonction de la façon dont on écrit à la console, vous choisissez le langage pour les mauvaises raisons. Je suis d'accord avec le
iostream
est complexe, mais il y a beaucoup d'aspects géniaux du langage qui ne sont pas du tout liés à iostream (par exemple, la STL). (Si vous n'aimez pas iostream, alors ne l'utilisez pas. Utilisez les éléments de<cstdio>
ou des éléments spécifiques à votre plate-forme).11 votes
@Billy : Ce n'est pas de l'écriture de la console dont je parlais, mais du fait qu'un débutant doit savoir surcharge des opérateurs avant même qu'il puisse commencer à comprendre ce qui se passe réellement...
2 votes
@Billy : En outre,
a << b;
devrait no aurait été une déclaration autorisée ; c'est comme dire2 + 3;
ce qui, bien que valable, n'a aucun sens. Si quoi que ce soit, ils auraient dû faire en sorte que ce soita <<= b;
pour qu'il donne au moins le indice au lecteur qu'une sorte de mission a réellement lieu.2 votes
@Mehrdad : Dire qu'une chose est mauvaise parce que vous ne la comprenez pas n'est pas un raisonnement suffisant pour prouver qu'elle est mauvaise.
2 << 3
n'invoque pas du tout la surcharge des opérateurs. Quant à l'illégalité, vous pouvez écrire des absurdités dans n'importe quel langage. Le rôle du langage n'est pas de vous empêcher de faire des choses stupides.1 votes
Err tu as modifié ton commentaire et maintenant le mien n'a plus autant de sens. Mais le point final est toujours vrai. Peut-on faire de mauvaises choses avec la surcharge des opérateurs ? Bien sûr. Mais juste parce que vous pouvez faire de mauvaises choses avec une fonctionnalité ne signifie pas que cette fonctionnalité ne devrait pas exister.
1 votes
@Billy : La surcharge des opérateurs et la définition d'une "déclaration" étaient séparé dont je parlais, les deux ayant leurs propres utilisations valables. Et ce n'est pas parce que vous le comprenez que c'est bon non plus... Je comprends certainement ce qui se passe, mais je pense toujours que c'est mauvais : tout comme l'expression
Two plus three
n'a aucun sens en tant que phrase en anglais, le code2 + 3;
oua << b;
n'a pas vraiment de sens en tant que déclaration et le fait qu'il soit valide rend le C++ très difficile à apprendre (sans parler du fait qu'il est plus facile pour vous de vous tirer une balle dans le pied).2 votes
@dreamlax : Eh bien, les gars hardcore C++ comme moi vont vouloir que vous utilisiez les iostreams bien sûr, mais il y a beaucoup de gens qui ne les aiment pas. Le C++ n'est pas un langage qui vous impose beaucoup de choses. Si vous n'aimez pas la bibliothèque, ne l'utilisez pas.
1 votes
@Mehrdad : Ce n'est pas le rôle d'une langue de rendre difficile le fait de se tirer dans le pied. C'est le travail du langage d'exprimer proprement ses pensées dans une forme que l'ordinateur peut comprendre. Dans un langage où l'on peut adresser la mémoire et provoquer des segfaults et des buffer overflows et toutes sortes d'autres choses désagréables, rendre difficile de se tirer dans le pied aurait été (et est) un objectif de conception insensé. Si vous voulez un langage avec de tels objectifs, alors dégagez de notre pelouse et allez utiliser Java ou C#.
5 votes
@Billy : Ce n'est pas la bibliothèque de flux d'E/S qui est le problème. Compte tenu de ce dont dispose le C++, la bibliothèque est plutôt bien écrite, en fait. Le problème est que le langue permet à peu près tout pour être une déclaration - quelque chose que beaucoup d'autres langages ne permettent pas, parce qu'il est honnêtement n'a aucun sens pour dire
2 + 3;
et cela ne fait que semer la confusion tant chez le programmeur que chez le lecteur. S'ils avaient effectivement forcé l'utilisation de certains affectation opérateur commecout <<= "hi";
au lieu decout << "hi";
A mon avis, le langage (et par conséquent la bibliothèque d'E/S) aurait été bien meilleur.0 votes
@Mehrdad : Ça n'a pas non plus de sens de faire
a.Select((x) => x)
(oùa
est unIEnumerable
) en C# non plus, mais le langage vous permet de le faire. Si vous voulez être stupide, vous pouvez l'être n'importe où. Si vous voulez que le langage soit "intuitif pour un débutant", alors n'utilisez pas C++.0 votes
@Billy : Ce n'est pas un langue question...
Select
ne fait pas partie du langage C#.0 votes
@Mehradad : Pourquoi est-ce important de savoir si c'est un problème de langue ? Unintuitif est unintuitif.
1 votes
Il est amusant de constater que de nombreux langages ont emprunté le style d'entrée-sortie du C (Ruby, Python, Shell, Go, Java, C# [dans une certaine mesure]), mais je n'en connais aucun qui utilise le style du C++.
0 votes
@Billy : Oui, tu as tout à fait raison, c'est tout aussi mauvais de
a.Select((x) => x)
en C# comme il l'est d'écrirea << b;
en C++, parce que ni l'un ni l'autre n'a vraiment de sens en tant que déclaration. Je ne suis pas sûr de ce que vous essayez de dire, cependant... cela ne fait que renforcer mon point de vue. :)0 votes
@Mehrdad : Ce que je veux dire, c'est que dire "Je peux faire en sorte que la fonctionnalité x fasse n'importe quoi !" ne justifie pas la suppression de cette fonctionnalité (du moins en ce qui concerne les langages de programmation à usage général). N'importe qui peut écrire du code dans n'importe quel langage en utilisant la plupart des fonctionnalités qui font des bêtises. Vous pouvez écrire des absurdités quand vous le souhaitez. Le langage n'exige pas que le code soit de haute qualité ; c'est la responsabilité du programmeur.
0 votes
@dreamlax : En fait, je suis d'accord avec vous ici - je ne suis pas un fan de iostreams - la principale raison pour laquelle je le préfère à cstdio est que iostreams facilite l'écriture de code testable ; cstdio ne fournit pas un moyen de faire (par exemple) une
FILE *
pointe vers une chaîne de caractères.0 votes
@Billy : Je suis no en disant
I can make feature x do nonsense!
; je dis Fonctionnalité x est C'est absurde ! , dondex
est la capacité de déclarations commea << b;
. Je suis no Je ne m'oppose pas à la surcharge des opérateurs, et je ne dis pas non plus tout ce qui est sur la bibliothèque d'E/S. Ce que je veux dire c'est que,a << b;
devrait être syntaxiquement non valide comme une déclaration pour la même raison queC++ needs.
est une phrase invalide en anglais : aucune des deux n'a beaucoup de sens. Si cela avait étéa <<= b;
ça aurait eu du sens, parce que=
implique l'effet secondaire d'une affectation, alors que<<
ne le fait pas.0 votes
@Mehrdad : Comment alors soutenez vous
a << b << c
?0 votes
@Billy : Je pense que vous n'avez pas compris :
a << b << c
devrait sont valables, maisa << b << c;
ne devrait pas . (Remarquez le;
.)0 votes
@Mehrdad : Ok,
a << b << c;
alors. C'est de la formeexpression;
que vous ne pouvez pas supprimer parce que c'est pourquoi (par exemple)a++;
travaux.0 votes
@Billy : C'est facile : vous Ne le fais pas. . (Voir C#, Java, D, et toute une série d'autres langages qui s'en passent parfaitement).
0 votes
Pouvez-vous être un peu plus précis ? Je pense que nous sommes tous deux d'accord pour dire que
a << b
doit être une expression possible. Je pense que nous sommes tous deux d'accord pour dire queexpression;
ne peut pas y aller, comme je l'ai déjà illustré. Comment résoudriez-vous exactement ce problème ?0 votes
@Billy : Oui, nous sommes tous deux d'accord pour dire que
a << b
doit être un possible expresssion . Non, nous ne no tous deux conviennent que tout doit être une expression valide déclaration ; en particulier,a << b;
devrait no être une déclaration valide, car le<<
L'opérateur fait no transmettre le fait qu'il provoque un affectation . Et d'ailleurs, C# fait no permettre cela.1 votes
Mais c'est no provoquant une affectation. C'est l'appel d'une fonction. Que l'utilisateur peut surcharger pour faire ce qu'il veut.
0 votes
@Billy : Regarde cette erreur C# lorsque tu tapes dans
1 << 2;
ou tout autre élément de ce typea << b
d'ailleurs :error CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
0 votes
@Billy : Si tu concevais une nouvelle version de l'anglais, laisserais-tu le phrase
C++ is not very.
être grammaticalement correct phrase ?1 votes
@Mehrdad : Ok, alors nous ne sommes pas d'accord. Retournez en 1978 pour faire changer d'avis Dennis Ritchie, et alors on pourra le faire. Le langage n'est pas conçu pour rendre un non-sens invalide parce que quelqu'un est un idiot. Il est conçu pour que quelqu'un qui sait ce qu'il fait puisse exprimer des idées. C# et C et C++ ont des objectifs de conception différents. Le C# a pour objectif d'éviter les absurdités. Ce n'est pas le cas de C et C++.
0 votes
Je ne vois pas en quoi vos exemples anglais ont quelque chose à voir avec les exemples C++.
0 votes
@Billy : La connexion est,
a + b;
en C++ est commeA plus B.
en anglais. Le second n'a pas de sens en tant que phrase, et le premier n'en a pas non plus en tant qu'affirmation... Je pense que cela suit très logiquement, étant donné que les humains sont censés lire du code et non des ordinateurs.1 votes
@Mehrdad : comme le dit Billy,
a << b
n'est pas nécessairement à l'origine d'une affectation. En ce qui concerne les flux, le débutant que vous tenez tant à protéger devrait penser à "flux b par a", et la nature vaguement fléchée et directionnelle du caractère moins que est utile.cout
ils ne se soucient pas de la mise en mémoire tampon : ils savent juste que les données ont été envoyées et sont parties, donc l'affectation serait trompeuse ("hé, ça ne reste pas coincé dans cout ? je ne peux pas le récupérer ?"). Et d'autres langages faire adopter le style C++ : par exemple, Ruby :$stdout << 99 << " red balloons"
... te semble familier ?0 votes
@Tony : Pourriez-vous lire le quatrième paragraphe en gras aquí ? C'est écrit : Ne faites pas le malin lors de la définition des surcharges d'opérateurs. La surcharge d'opérateurs est utile dans les cas où le résultat de l'opération est immédiatement évident. Par exemple, il est logique de pouvoir soustraire un objet DateTime d'un autre objet DateTime pour obtenir un objet TimeSpan. Cependant, il est no approprié d'utiliser l'opérateur d'union logique pour unir deux requêtes de base de données, ou d'utiliser l'opérateur shift pour écrire dans un flux . (c'est moi qui souligne)
0 votes
@Tony : ... et ne le dénoncez pas comme étant spécifique à C#. Il s'applique à bien d'autres langages que C#, et la section raison derrière le "ne faites pas le malin". -- à savoir lisibilité humaine -- s'applique partout . Il n'y a pas de raison de rendre les choses plus compliquées qu'elles ne doivent l'être ; c'est là que le C++ a échoué, avec des choses comme mauvaise utilisation de la surcharge de l'opérateur et du mauvais choix d'autoriser tout expression quelconque pour être considérée comme une déclaration.
0 votes
@Mehrdad : Le coup bas de MSDN est exactement ça. "C++ a échoué" ? Je suis désolé, mais je n'accepte pas votre autoproclamation en tant que juge de cela. La lisibilité est importante, et étant donné l'expérience pratique d'enseignement que Stroustrup a eue, je suis sûr qu'il aurait fait quelque chose à propos de << si les nouveaux développeurs avaient des problèmes avec ça. Vous êtes juste mélodramatique, mais n'hésitez pas à utiliser les macros variadiques de C++0x pour implémenter un "print(a, b, c)" sûr du point de vue du type si le BASIC vous manque. ;-P
0 votes
@Tony : Donc vous pensez que MSDN a juste dit ça pour promouvoir C# contre ? Si oui, comment est-ce une promotion - est-ce parce que (Dieu nous en préserve !) c'est un bon conseil ? Si non, alors pourquoi avoir dit cela ? Juste pour induire les gens en erreur ? Aussi, vous êtes à nouveau manquant le fait que je ne fais pas référence à l'I/O ! Je fais référence à la façon dont les expressions et les déclarations sont traitées en général... Je ne sais pas pourquoi vous mentionnez systématiquement le problème des E/S, car je ne fais en aucun cas de distinction entre iostream et toute autre partie du C++.
1 votes
@Tony : Essayez de jeter un coup d'oeil à cette page qui ont à voir avec le C++ lui-même : Si vous fournissez des opérateurs constructifs, ils ne doivent pas modifier leurs opérandes . Par exemple,
x + y
ne devrait pas changerx
. (Idem avec<<
.)0 votes
@Tony : Eh ?
Given the hands-on teaching experience Stroustrup has had I'm sure he'd have done something about << if new developers had trouble with it.
Vous pensez donc que les débutants n'ont aucun problème avec ça ? Pour une chose, I J'ai eu des problèmes avec ça quand j'étais débutant. D'autre part, je ne suis pas vraiment seul ; mes amis me posent la même question lorsqu'ils apprennent le C++, et même d'autres me demandent cette même question sur SO. Je doute que Stroustrup ait eu l'œil d'un débutant lorsqu'il a conçu le C++, et je ne vois pas pourquoi vous avez qualifié cela de coup bas.