Je veux écrire une fonction qui génère quelque chose à un ostream code> qui est transmis et renvoie le flux, comme celui-ci:
Value: 12
7 Réponses :
Vous voulez faire de Myprint une classe avec un ami Opérateur d'ami XXX PRE>
Cette méthode vous oblige à insérer l'objet Myprint dans le flux de votre choix. Si vous avez vraiment besoin de la possibilité de modifier quel flux est actif, vous pouvez le faire: P>
class MyPrint { public: MyPrint(int val, std::ostream& os) : val_(val), os_(os) {} friend std::ostream& operator<<(std::ostream& dummy, const MyPrint& mp) { mp.os_ << mp.val_; return os_; } private: int val_; std::ostream& os_ }; int main(int argc, char** argv) { std::cout << "Value: " << MyPrint(12, std::cout) << std::endl; return 0; }
Sauf que cela ne fait pas ce qui a été demandé.
Eh bien, pour commencer, il ne compile pas.
Oups. Mauvaise copie / pâte. Merci d'attraper.
Ce n'est pas obligé d'être un ami; Il utilise uniquement des méthodes publiques de STD :: Onetream.
Faites-en une classe de modèle et ajoutez une fonction de modèle pour la créer et sa parfaite.
@Max Lybbert: Cela accède à une variable de membre privé?
C'est exactement comment j'aurais répondu à cette question
Désolé, "il utilise uniquement des méthodes publiques de STD :: Onetream, donc il n'a pas besoin d'être un ami du STD :: Onetream; car c'est une méthode de maprint, il a déjà accès à des méthodes privées et à des variables de MyPrint et n'a pas besoin d'être un ami de maprint non plus (plus une classe ne peut pas être un ami de lui-même). "
@Max Lybbert. 1) Qu'entendez-vous par "méthode" i>? 2) La fonction opérateur <<< / code> dans son code est pas i> membre de la classe. Supprimer le mot-clé ami en ferait un membre, mais ferait le code non valide, car un opérateur
membre <<< / code> doit avoir un seul paramètre. C'est ce qu'on appelle une "définition d'ami" i>.
J'ai mis des explications ici: Stackoverflow.com/questions/991518/...
Merci pour la correction. Comme vous pouvez le constater de ma réponse, je les ai généralement définis comme des fonctions non membres.
Tout d'abord, il n'y a aucune raison de ne pas passer dans le si vous ne voulez vraiment pas utiliser ostream code> par référence plutôt que par un pointeur:
Std :: Ostream & Opérateur , vous pouvez le faire: P>
int main(int argc, char** argv){
std::cout << "Value: ";
MyPrint(12, std::cout) << std::endl;
return 0;
}
"Il n'y a aucune raison de ne pas transmettre l'ostream par référence". Certaines personnes n'aiment pas les paramètres de référence non-Const. Je ne suis pas d'accord avec eux, mais je ne disais pas qu'il n'y a "aucune raison" pour leur préférence.
Je ne vois pas comment un pointeur non-Const serait préférable à une référence de non-Const dans une norme de codage en sens unique.
Google dit "Les références peuvent être déroutantes, car elles ont une valeur de syntaxe de valeur, mais la sémantique du pointeur" ( Google-styleguide.googlecode.com/svn/trunk/... ). Je pense qu'ils veulent dire que la valeur pass-valeur et la référence pass-référence ressemble à la même chose sur le site d'appel. Ils pensent donc que le code est plus lisible si les lecteurs peuvent supposer que tout ressemble à une valeur de passage, laisse la valeur non modifié. Et comme dit le proverbe, Google est insensé comme un renard. Il a des attitudes légèrement à l'ancienne à C ++, mais je pense pas irrationnelle.
L'opérateur standard <<< / code> La notation prend le
std :: ostream code> par référence comme une entrée; Puisque ce gars tente d'émuler la fonctionnalité d'Onetream, il serait préférable de faire correspondre la syntaxe plutôt que de transmettre une référence. De plus, il retourne une référence au pointeur déréférencé! Si vous avez utilisé un pointeur, vous devriez appeler quelque chose comme
myprint (12, & (std :: cout << ":")); code> qui est juste gênant. Vous passez un pointeur à un objet temporaire.
"L'opérateur standard << NOTATION prend le STD :: Onetream par référence comme une entrée". Oui, Google Notes "nécessaires à certaines applications" en tant que "con" de leur règle "Aucune référence non-Const". C'est parmi les raisons pour lesquelles je suis en désaccord avec la règle: c'est un joli tueur "con" :-)
Dans votre cas, la réponse est évidemment: si cela ne suffit pas, veuillez expliquer quelle sortie vous voulez voir. p> p>
L'exemple est évidemment simplifié et montre que l'utilisateur souhaite comprendre comment chaîner des opérations de flux.
Contrairement à beaucoup de gens rond ici, je n'ai pas la facilité heureuse de comprendre la question «évidente» non montagtérielle - j'aime avoir des choses énoncées.
Je pense que vous devriez changer votre icône dans une étoile de mer grincheuse face à face :-(
Si vous pouvez en trouver un, je l'utiliserai volontiers.
Vous ne pouvez pas corriger la fonction. Rien dans la spécification ne nécessite qu'un compilateur d'évaluer une fonction d'appel dans une expression dans un ordre particulier par rapport à un opérateur non apparenté dans la même expression. Donc, sans modifier le code d'appel, vous ne pouvez pas faire ordre de gauche à droite est mandaté pour les expressions consistant en plusieurs "opérateurs consécutifs", de sorte que cela fonctionnera. Le point de l'opérateur Vous ne pouvez pas obtenir la même chose avec libre Appels de fonction parce qu'ils n'ont pas de LHS. car la sortie souhaitée est la suivante: P> myprint () code> évaluer après
std :: cout
myprint () code> renvoie un objet égal à
std :: cou code>, et donc
std :: cout , donc vous "Réfirements" Code> STD :: COUT , qui imprime cette valeur hexagonale. p>
class WhateverItIsYouReallyWantToPrint {
public:
void print(ostream &out) const {
// do whatever
}
};
ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
obj.print(out);
}
Je sais que j'ai toujours trouvé plus facile de casser des ruisseaux dans des appels de fonction traditionnels lorsque je ne peux pas avoir la tête autour de quelque chose, alors je pensais ajouter cela pour que l'OP au cas où elle les aide aussi. J'espère que ça ne vous dérange pas. Je pense que j'ai raison de dire que la ligne STD :: Cout la ligne se résume essentiellement à Cout.Operator << ("Valeur:") .Opérateur << (myprint (12 et std :: Cout)) :: endl); Ce qui pourrait être un moyen plus facile de visualiser ce que cette réponse dit.
J'ai mis à jour la question; Il dit maintenant que la sortie souhaitée serait la valeur: 12.
@Stevejessop Vous avez probablement oublié de mettre retour code> à la fin de
opérateur <<< / code> Mise en œuvre:
retour; code>.
Il n'y a aucun moyen de faire ce que vous attendez en raison de la commande que les fonctions sont évaluées. P>
Y a-t-il une raison particulière dont vous avez besoin pour écrire directement à l'ostream comme ça? Sinon, j'ai juste myprint retourner une chaîne. Si vous souhaitez utiliser un flux à l'intérieur de MyPrint pour générer la sortie, utilisez simplement une tension et renvoyez le résultat. P>
Vous avez deux options. Le premier, en utilisant ce que vous avez déjà, c'est:
#include <iostream> struct X { int y; }; // I'm not bothering passing X as a reference, because it's a // small object std::ostream& operator<<(std::ostream& os, const X x) { return os << x.y; } int main() { X x; x.y = 5; std::cout << x << std::endl; }
Après avoir changé le pointeur sur une référence, vous pouvez le faire:
#include <iostream> std::ostream& MyPrint(int val, std::ostream& out) { out << val; return out; } int main(int, char**) { MyPrint(11, std::cout << "Value: ") << std::endl; return 0; }
Pourquoi passez-vous le flux via un pointeur plutôt que via une référence?
Peut-être a-t-il lu le Guide de style Google et a acheté dans cette «NE PAS UTILISER LES PARAMÈTRES DE REFERENCE NON-CONSTRISSE».
En outre, quel est le point de ne pas faire
cout << "valeur:" << 12; code> comme @Neil recommande? Cela semble être la solution la plus simple.
@Neil et @oneByone: Oui, j'ai commencé à utiliser les conventions de style Google.
@LitB: Il suffit d'imprimer '12' n'était qu'un exemple de jouet. En réalité, je ne transmette pas d'int, mais une structure de données plus compliquée qui doit être imprimée au flux.
@dehmann Veuillez cesser d'utiliser les conventions Google. Si vous avez besoin de raisons, il y a eu une grande discussion à ce sujet sur la Comp.lang.c ++. Groupe de discussion de USenet modéré.
Re: Update2 - Pour imprimer cet objet complexe de la vôtre, pourquoi non seulement définir un nouvel opérateur STD surchargé :: << pour ce type, tout comme tous les autres utilisations de la classe normale?