Question

Il est bien connu que l'utilisateur peut définir Manipulateurs flux comme ceci:

ostream& tab(ostream & output)
{
    return output<< '\t';
} 

Et cela peut être utilisé dans main () comme ceci:

cout<<'a'<<tab<<'b'<<'c'<<endl;

S'il vous plaît expliquez-moi comment ça fonctionne? Si opérateur << prend comme second paramètre un pointeur sur la fonction qui prend et retourne ostream & , puis s'il vous plaît expliquer mon pourquoi il est nécessaire? Quel serait mauvais si la fonction ne et mais il était pas prendre et le retour ostream vide au lieu de ostream & ?

En outre, il est intéressant pourquoi Manipulateurs « dec », « Hex » prennent effet jusqu'à ce que je ne change pas entre eux, mais Manipulateurs définis par l'utilisateur doit toujours être utilisé afin de prendre effet pour chaque diffusion en continu?

Était-ce utile?

La solution

La norme définit la surcharge de operator<< suivante dans le modèle de classe basic_ostream:

basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& (*pf) (basic_ostream<charT,traits>&) );
  

Effets: Aucun. Ne se comporte pas en fonction de sortie formatée (tel que décrit dans 27.6.2.5.1).

     

retour. pf(*this)

Le paramètre est un pointeur sur une prise de fonction et de retourner une référence à un std::ostream.

Cela signifie que vous pouvez « flux » une fonction avec cette signature à un objet ostream et il a pour effet d'appeler cette fonction sur le flux. Si vous utilisez le nom d'une fonction dans une expression alors il est (généralement) converti en un pointeur vers cette fonction.

std::hex est un manipulateur de std::ios_base défini comme suit.

   ios_base& hex(ios_base& str);
  

Effets:. Appels str.setf(ios_base::hex, ios_base::basefield)

     

Renvoie:. Str

Cela signifie que le streaming hex à un ostream établira la base de sortie mise en forme des drapeaux aux numéros de sortie en hexadécimal. Le manipulateur ne se rien ne sort pas.

Autres conseils

Il n'y a rien de mal avec elle sauf qu'il n'y a pas de surcharge << opérateur défini pour elle. Les << existants pour les surcharges s'attendent à un manipulateur avec la signature ostream & (* fp) (ostream &) .

Si vous avez donné un manipulateur du type ostream & (* fp) () vous obtiendrez une erreur de compilation car il ne pas ont une définition pour opérateur << (ostream &, ostream & (* fp) ()) . Si vous vouliez cette fonctionnalité vous devez surcharger l'opérateur << accepter Manipulateurs de ce type.

Vous devrait écrire une définition pour ceci:
ostream & ostream :: operator << (ostream & (* m) ())

Gardez à l'esprit ici que rien de magique qui se passe ici. Les bibliothèques de flux comptent beaucoup sur standard C ++ fonctions: surcharge opérateur, des classes et des références.

Maintenant que vous savez comment vous pouvez créer les fonctionnalités que vous avez décrite, voici pourquoi nous ne sommes pas:

Sans passer une référence au flux que nous essayons de manipuler, nous ne pouvons pas apporter des modifications au flux relié au dispositif final (cin, dehors, err, fstream, etc.). La fonction (modificateur de sont toutes les fonctions seulement avec des noms de fantaisie) devrait soit retourner une nouvelle ostream qui n'a rien à voir avec celui à gauche du << opérateur, ou par un mécanisme très laid, savoir quel ostream il se doit se connecter avec tout le reste à droite du modificateur ne vais pas le faire au dispositif final, mais serait plutôt envoyé à tout ce ostream la fonction / modificateur de retour.

Pensez courants comme celui-ci

cout << "something here" << tab << "something else"<< endl;

vraiment signifie

(((cout << "something here") << tab ) << "something else" ) << endl);

où chaque ensemble de parenthèses fait quelque chose à Cout (écrire, modifier, etc.) et retourne ensuite Cout de sorte que la prochaine série de parenthèses peut travailler.

Si votre modificateur onglet / fonction n'a pas une référence à un ostream il aurait à deviner en quelque sorte ce que ostream était à gauche du << opérateur pour effectuer sa tâche. Avez-vous travaillé avec cour, cerr, certains flux de fichiers ...? Les internes de la fonction ne connaîtront jamais à moins d'être remis cette information d'une façon, et pourquoi pas comment être aussi simple comme référence.

Maintenant, pour vraiment conduire la maison point, regardons ce que endl est vraiment et quelle version surchargée de l'opérateur << que nous utilisons:

Cet opérateur se présente comme suit:

  ostream& ostream::operator<<(ostream& (*m)(ostream&)) 
  {  
      return (*m)(*this);
  }

ressemble Endl comme ceci:

  ostream& endl(ostream& os)      
  {  
      os << '\n'; 
      os.flush();     
      return os;
  }

Le but de endl est d'ajouter une nouvelle ligne et rincez le flux, en veillant à tous ont été écrits le contenu de la mémoire tampon interne du flux vers l'appareil. Pour ce faire, il faut d'abord écrire un « \ n » à ce flux. Il faut alors dire le flux de rinçage. La seule façon pour endl de savoir quel flux écrire à et rinçage est pour l'opérateur de transmettre cette information à la fonction endl quand il l'appelle. Ce serait comme moi vous dire de laver ma voiture, mais jamais vous dire quelle voiture est la mienne dans le lot complet de stationnement. Vous ne seriez jamais capable de faire votre travail. Vous avez besoin de moi à chaque main que vous ma voiture ou je peux laver moi-même.

J'espère que les choses Clears

PS -. Si vous ne vous arrive de trouver accidentellement ma voiture, s'il vous plaît laver

Normalement, le manipulateur de flux définit des drapeaux (ou d'autres paramètres) sur l'objet de flux, de sorte que la prochaine fois il est utilisé, il agira selon les drapeaux. Le manipulateur retourne donc le même objet de son passé. La surcharge de operator<< qui a appelé le manipulateur a déjà cet objet, bien sûr, alors que vous avez remarqué, la valeur de retour est pas strictement nécessaire pour ce cas. Je pense que cela couvre tous les manipulateurs standards -. Ils ont tous leur retour d'entrée

Cependant, avec la valeur de retour, le cadre est suffisamment souple qu'un manipulateur de flux personnalisé peut retourner un autre objet, probablement une enveloppe pour l'objet donné son. Cet autre objet serait alors retourné de cout << 'a' << tab, et pourrait faire quelque chose que les paramètres formatage ostream intégré ne prennent pas en charge.

Je ne sais pas comment vous arrangez pour cet autre objet à être libéré, mais, donc je ne sais pas comment cela est pratique. Il aurait peut-être quelque chose de particulier, comme un objet proxy qui est géré par le ostream lui-même. Ensuite, le manipulateur ne fonctionne que pour les classes de flux personnalisé qui soutiennent activement, ce qui est généralement le point de manipulateurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top