Fonction qui imprime quelque chose à std::ostream et retourne std::ostream?
Je veux écrire une fonction qui renvoie à quelque chose d'un ostream
qui est passé en, et de renvoyer le flux, comme ceci:
std::ostream& MyPrint(int val, std::ostream* out) {
*out << val;
return *out;
}
int main(int argc, char** argv){
std::cout << "Value: " << MyPrint(12, &std::cout) << std::endl;
return 0;
}
Il serait pratique de pouvoir imprimer la valeur de ce genre et incorporer l'appel de la fonction dans l'opérateur de sortie de la chaîne, comme je l'ai fait dans main()
.
Ça ne fonctionne pas, cependant, et imprime ce:
$ ./a.out
12Value: 0x6013a8
La sortie désirée serait celui-ci:
Value: 12
Comment puis-je résoudre ce problème? Dois-je définir un operator<<
à la place?
Mise à JOUR: a Précisé que la sortie désirée serait.
UPDATE2: Certaines personnes ne comprenaient pas pourquoi j'ai l'impression d'un nombre comme ça, à l'aide d'une fonction au lieu de l'imprimer directement. C'est un exemple simplifié, et, en réalité, la fonction imprime un objet complexe, plutôt que d'un int
.
- Pourquoi êtes-vous le passage du courant par l'intermédiaire d'un pointeur plutôt que par le biais de areference?
- Peut-être qu'il est lire la Google guide de style, et acheté dans ce "ne pas utiliser de non-const paramètres de référence" de la mode qui va autour.
- Aussi, quel est le point de ne pas faire
cout << "Value: " << 12;
comme @Neil recommande? Qui semble être la plus simple solution. - et @onebyone: Oui, j'ai commencé à utiliser google conventions de style.
- Juste l'impression de '12' était juste un exemple jouet. En réalité, je ne passe pas un int, mais plus compliqué structure de données qui doit être imprimé sur le flux.
- Veuillez cesser d'utiliser le google conventions. Si vous avez besoin de raisons, il y avait une grande discussion à ce sujet sur le comp.lang.c++.modérateur de groupe de discussion usenet.
- Re: UPDATE2 -- À l'impression de cet objet complexe de la vôtre, pourquoi ne pas définir une nouvelle surchargé std::operator<< pour ce type, comme à chaque classe normale utilise?
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas régler la fonction. Rien dans la spécification nécessite un compilateur pour évaluer un appel de fonction dans une expression dans un ordre particulier à l'égard de certains indépendants de l'opérateur dans la même expression. Ainsi, sans changer le code appelant, vous ne pouvez pas faire
MyPrint()
évaluer aprèsstd::cout << "Value: "
De gauche à droite est obligatoire pour les expressions composées de plusieurs consécutives << les opérateurs, de sorte que ce sera le travail. Le point de l'opérateur<< renvoyer le flux de données est que lorsque les opérateurs sont enchaînés, le membre de GAUCHE de chacun est fourni par l'évaluation de l'opérateur à sa gauche.
Vous ne pouvez pas réaliser la même chose avec la gratuit des appels de fonction parce qu'ils n'ont pas de GAUCHE.
MyPrint()
retourne un objet est égale àstd::cout
, et donc nestd::cout << "Value: "
, de sorte que vous êtes en fait unstd::cout << std::cout
, qui est l'impression que valeur hex.Depuis la sortie désirée est:
la "bonne" chose à faire est en effet de remplacer l'opérateur<<. Cela signifie que vous devez soit faire un ami, ou de le faire:
Si une substitution de
operator<<
pour votre classe n'est pas approprié, par exemple parce qu'il y a de multiples formats que vous pouvez l'imprimer, et vous voulez écrire une fonction différente pour chacun, alors vous devez soit renoncer à l'idée de l'opérateur de chaînage et il suffit d'appeler la fonction, ou bien écrire plusieurs classes prendre votre objet en tant que paramètre du constructeur, chacun avec différentes surcharge de l'opérateur.return
déclaration à la fin deoperator<<
mise en œuvre:return out;
.Vous voulez faire MyPrint une classe avec un ami de l'opérateur<<:
Cette méthode nécessite l'insertion d'une MyPrint objet dans le flux de votre choix. Si vous avez VRAIMENT besoin de la capacité de changer le flux de données est active, vous pouvez le faire:
operator<<
dans son code est pas un membre de la classe. Retrait de l'ami de mots clés faire un membre, mais rendrait le code non valide, car un membreoperator<<
doit avoir un seul paramètre. Ça s'appelle un "ami de la définition de".Vous avez deux options. La première, en utilisant ce que vous avez déjà est:
L'autre, qui est plus similaire à C++, est de remplacer
MyPrint()
avec lestd::ostream& operator<<
. Il y a déjà un pourint
, donc je vais faire un juste un peu plus complexe:Il n'y a aucun moyen de faire ce que vous attendez là, à cause de l'ordre, les fonctions sont évaluées.
Est-il une raison particulière pour laquelle vous devez écrire directement à l'ostream comme ça? Si non, il suffit d'avoir MyPrint retourner une chaîne de caractères. Si vous souhaitez utiliser un flux à l'intérieur de MyPrint pour générer la sortie, il suffit d'utiliser un strstream et de retourner le résultat.
Tout d'abord, il n'y a aucune raison de ne pas passer dans le
ostream
par référence plutôt que par un pointeur:Si vous ne voulez vraiment pas à utiliser
std::ostream& operator<<(std::ostream& os, TYPE)
, vous pouvez le faire:operator<<
notation prend lastd::ostream
par référence comme une entrée; depuis que ce mec est tentant de reproduire les ostream de la fonctionnalité, il serait mieux pour correspondre à la syntaxe plutôt que de passer une référence. De Plus, il renvoie une référence à l'pointeur déréférencé! Si vous avez utilisé un pointeur, vous devez appeler quelque chose commeMyPrint(12, &(std::cout << "Value:") );
qui est juste maladroit. Vous êtes en passant un pointeur vers un objet temporaire.Après la modification du pointeur à une référence, vous pouvez le faire:
La syntaxe pour
MyPrint
est essentiellement celui d'un dérouléoperator<<
mais avec un argument supplémentaire.Dans votre cas, la réponse est évidemment:
Si ce n'est pas assez bon, expliquer ce qu'est sortie que vous voulez voir.