Après avoir regardé le J'ai remarqué les déclarations suivantes: p> mais je découvert qu'il existe également les déclarations suivantes: p> Pourquoi les opérateurs de sortie de caractère / chaîne ne sont pas des fonctions membres? p> p> ostream :: opérateur <<< / code> C ++ Référence,
5 Réponses :
Le premier groupe d'opérateurs sont membres de la classe de flux. p>
La plupart des surcharges de l'opérateur, comme ceux du second groupe, ne sont pas. p>
sur le pourquoi em>, il est probablement juste un accident historique. Les opérateurs pour types intégrés peuvent être ajoutés aux classes de flux et, évidemment, ils étaient (bien avant que C ++ soit normalisé). La norme documente simplement la pratique existante ici. P>
Les opérateurs pour les types définis par l'utilisateur ne peuvent évidemment pas être ajoutés aux classes de flux. Ils sont donc mis en œuvre comme fonctions libres. p>
rétrospectivement, il aurait été plus cohérent de rendre tous les fonctions libres des opérateurs, mais cela permettrait de casser de vieux programmes. P>
Savez-vous pourquoi i> ces standards Char code> Les surcharges n'ont pas été fabriqués des membres de la classe de flux?
@ Drewdormann pourrait être une bonne question à elle seule. Je pense que je pense que je me souvienne d'avoir déjà vu des problèmes (alors des questions) causés indirectement par cette distinction.
@Christianrau des commentaires ici, je soupçonne cette question i> est cette question i>.
Oui, c'est le problème principal ici;)
@Trewdormann, j'ai une théorie, n'hésitez pas à commenter ma réponse si vous pensez que cela n'a aucun sens
@ Awrewdormann & Rouki, dans ce cas, la question a besoin d'un peu de nettoyage, clarifiant que l'OP est conscient du fait que l'un est membre et que l'un n'est pas et ne demandant pas la raison plus profonde. Mais les deux questions dans une (et même sans clarification qui la questionner est) est liée à attirer supposément "mal" i> i> ou "incomplète" i> réponses (comme beaucoup d'excitations < I> après i> cette clarification).
Je n'aurais probablement pas dû demander à la fois sur le même sujet. Quoi qu'il en soit, j'ai édité le poste.
@Bo, je suis en désaccord sur l'accident historique. Je pense qu'ils ne peuvent pas être ajoutés à la classe, car il existe différentes implémentations pour basic_ostream
basic_ostream
@Zdeslavvojkovic Vous pouvez très bien spécialiser des membres individuels, tout simplement pas en les spécialisant directement, mais déléguant des parties du travail à d'autres sous-composantes (éventuellement spécialisées), comme les traits de caractère ou les paramètres régionaux (ce qu'ils sont réellement faits pour , résumant la fonctionnalité dépendante du type charret en composants plus petits et spécialisables). Pensez à une méthode classique GOF "Modèle" i> (modèle dans le sens de la GOF, pas le sens C ++).
@Zdeslavvojkovic - L'accident historique est que basic_ostream :: opérateur << (int) code> est membre. Ce n'est pas obligé d'être.
@Bopersson, oh, droite - j'ai compris Les opérateurs des types intégrés peuvent être ajoutés aux classes de flux code> comme référence
char code>.
@Christianrau, bien sûr mais c'est beaucoup plus complexe que de les avoir comme des fonctions globales
@Zdeslavvojkovic "Mais c'est beaucoup plus complexe que de les avoir comme des fonctions globales" i> pourquoi. Les traits de caractère et les locaux sont conçus pour exactement cet objectif. Pourquoi rendre le flux et les opérateurs les prennent comme des arguments de modèle quand alors ne les utilisez pas i> et de faire clairement les mêmes opérations qu'ils sont censées faire et peuvent déjà faire en doublonnation de fonction unie. C'est contre tous les principes de la générosité de code et en évitant la duplication de code qui construisent la base de la conception de la bibliothèque standard (et en général une bonne bibliothèque).
@Zdeslavvojkovic, je préférerais une seule méthode de modèle qui possède un code générique (qui ne dépend pas du flux et des types de caractères) une seule fois et délégués du code spécialisé aux traits spécialisés (comme celui-ci est fait dans la bibliothèque standard), qu'un groupe des surcharges effectuant exactement les mêmes pièces de code sur et sur un souci de spéciliation de certaines petites parties du code (et ignorant complètement les traits déjà donnés).
La première série sont les fonctions des membres, que La deuxième série sont des fonctions autonomes (telles que vous dites que vous pouvez ajouter pour n'importe quelle classe afin que vous puissiez les diffuser à un Notez que les deux fonctionnent de la même manière sur un site d'appel. P> retour * Ceci code> pour la chaîne d'opérateur de l'opérateur. P>
std :: ostream code>), qui n'ont pas
ceci code > Pour revenir et
Retour OS code> au lieu de rendre le travail de chaînage de l'opérateur. p>
ma compréhension de la question est que le fait est que c'est pourquoi sont-ils séparés, pas quelle est la différence
Demandé à la fois d'être honnête;)
@Zdeslavvojkovic La réponse est la même chose, car les questions posent la même chose: les premiers font partie de la classe, alors savent déjà ce que std :: ostream et code> pour revenir, ce dernier a besoin d'un argument supplémentaire.
Peut-être que je n'étais pas clair: la partie déroutante est pourquoi ne pas les avoir tous en tant que membres ou tous comme non membres.
Il y a en fait deux familles de surcharger Une famille est l'élément surchargé Lorsque vous souhaitez ajouter une capacité de diffusion en continu à une classe de votre choix, vous ajoutez une fonction gratuite. P> opérateur <<< / code> s, comme vous l'avez découvert. p>
ostream :: opérateur <<< / code> (qui obtient la référence
ostream code> implicitement en tant que
Ceci code> Pointeur) et le Une autre famille est la fonction gratuite surchargée
<<< / code> qui obtient la référence
ostream code> explicitement comme un argument. p>
D'accord, et y a-t-il une bonne raison pour laquelle les opérateurs de sortie de caractère, non signé, ..., Const non signé Char * sont déclarés à différents endroits?
@Rouki: une raison: suppose que vous avez une instance s code> d'une classe qui n'est pas un
ostream code>, mais a un opérateur de conversion sur
ostream code>. Si
opérateur <<< / code> n'étaient qu'un membre de
ostream code> puis
s << 1 code> ne compilerait bien sûr pas. Cependant, avec la fonction libre, le compilateur peut voir qu'il existe une fonction pouvant correspondre si
s code> était un
ostream code> - et que savez-vous? Il y a un opérateur de conversion qu'il peut utiliser pour le faire! Vous trouverez de nombreux opérateurs définis comme des fonctions libres (par exemple, voir ici ) pour cette raison.
Les fonctions libres ne transmettent pas les fonctions des membres - notez qu'ils ont des types d'entrée différents. Le sous-classement n'est pas une raison pour cette différence, car une référence à dérivée peut être convertie en une référence à la base de toute façon. Je ne connais pas la raison même.
@Aschepler: True, j'avais à l'esprit le cas où il pourrait y avoir un comportement polymorphique. Corrigée. En ce qui concerne le sous-classement, je n'obtiens pas bien ce que vous parlez de? L'exemple ci-dessus n'a pas à faire avec le sous-classement.
@aschepler, je pense qu'il est lié à la spécialisation en fonction de la largeur de caractère cible - j'ai plus d'informations dans ma réponse
Les autres ont décrit les différences, voici mon tir de la raison pour laquelle ils sont divisés.
Les versions non membres, qui prennent des variantes code> Char code> car les paramètres sont spécialisés en fonction du type du flux cible. Type de caractère de base et manipulé en fonction de la locale, car la norme définit un comportement spécifique ( par exemple s'ils ont été définis comme des fonctions membres, vous ne seriez pas en mesure de Spécialisez-les comme ça, comme vous l'avez besoin de spécialiser partiellement toute la classe, pas seulement un seul membre, car la norme n'autorise pas la spécialisation partielle des fonctions des membres. P> P> o << '1' code> a un comportement différent de celui de
oo << 33 code>, il doit être manipulé correctement Si
o code> est
basic_ostream
Char CODE> ECRITEN À
BASIC_OSTREAM
basic_ostream
<<< / code>, par exemple: p>
Mais encore une fois, vous ne pouvez pas spécialiser des modèles de fonction autonomes (ou du moins que vous ne pouviez pas i> au moment de ces opérateurs ont été ajoutés à la norme, mais peut-être en C ++ 98, ils n'étaient pas autonomes du tout? ). En fin de compte, vous pouvez les personnaliser aussi facilement (ou peut-être encore plus facilement) s'ils étaient des fonctions membres. Et par exemple L'élargissement et ce genre de choses sont les traits de caractère et les locaux spécialisés, pas besoin de spécialiser les opérateurs de flux, je pense.
En fait, ce n'est pas une spécialisation partielle, mais une surcharge, non? J'ai édité la réponse. Le problème similaire est discuté ici: gotw.ca/gotw/049.htm
La raison de l'opérateur << Prise de charcuterie n'est pas une fonction de membre est qu'il existe déjà des fonctions définies dans OStream qui écrivent des caractères au flux.
XXX PRE>Par conséquent, ces opérateurs sont fabriqués non Fonctions membres qui utilisent à l'interne ces deux fonctions. p> p>
duplicaté possible de Pourquoi opérateur >> (ou <<) La fonction de surcharge doit recevoir une référence I \ Otstream? a>
@Bopersson, pas de duplicata, cette question concerne les types définis par l'utilisateur.