ah
#include "logic.h"
...
class A
{
friend ostream& operator<<(ostream&, A&);
...
};
logic.cpp
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...
Quand je compile, il dit:
std :: ostream & logic :: operator << (std :: ostream &, A &) 'doit prendre exactement un argument.
Quel est le problème?
c++
operator-overloading
iostream
En tant que
la source
la source
Une fonction ami n'est pas une fonction membre, donc le problème est que vous déclarez
operator<<
comme ami deA
:puis essayez de le définir comme une fonction membre de la classe
logic
Êtes-vous confus quant à savoir s'il
logic
s'agit d'une classe ou d'un espace de noms?L'erreur est due au fait que vous avez essayé de définir un membre en
operator<<
prenant deux arguments, ce qui signifie qu'il prend trois arguments, y compris lethis
paramètre implicite . L'opérateur ne peut prendre que deux arguments, de sorte que lorsque vous écriveza << b
les deux arguments sonta
etb
.Vous voulez définir
ostream& operator<<(ostream&, const A&)
comme une fonction non- membre, certainement pas comme membre delogic
car cela n'a rien à voir avec cette classe!la source
J'ai rencontré ce problème avec des classes basées sur des modèles. Voici une solution plus générale que j'ai dû utiliser:
Maintenant: * Ma fonction toString () ne peut pas être en ligne si elle va être cachée dans cpp. * Vous êtes coincé avec du code dans l'en-tête, je n'ai pas pu m'en débarrasser. * L'opérateur appellera la méthode toString (), elle n'est pas en ligne.
Le corps de l'opérateur << peut être déclaré dans la clause friend ou en dehors de la classe. Les deux options sont laides. :(
Peut-être que je ne comprends pas bien ou que je manque quelque chose, mais simplement déclarer en avant le modèle d'opérateur ne lie pas dans gcc.
Cela fonctionne aussi:
Je pense que vous pouvez également éviter les problèmes de création de modèles qui forcent les déclarations dans les en-têtes, si vous utilisez une classe parente qui n'est pas basée sur un modèle pour implémenter l'opérateur <<, et utilisez une méthode virtuelle toString ().
la source
Si vous définissez en
operator<<
tant que fonction membre, elle aura une syntaxe décomposée différente de celle si vous utilisiez un non-membreoperator<<
. Un non-membreoperator<<
est un opérateur binaire, où un membreoperator<<
est un opérateur unaire.Alors ... comment les appelez-vous vraiment? Les opérateurs sont étranges à certains égards, je vous mets au défi d'écrire la
operator<<(...)
syntaxe dans votre tête pour donner un sens aux choses.Ou vous pouvez essayer d'appeler l'opérateur binaire non membre:
Vous n'avez aucune obligation de faire en sorte que ces opérateurs se comportent de manière intuitive lorsque vous les transformez en fonctions membres, vous pouvez définir
operator<<(int)
pour déplacer à gauche une variable membre si vous le souhaitez, comprenez que les gens peuvent être un peu pris au dépourvu, quel que soit le nombre de commentaires que vous pouvez écrire.Presque enfin, il peut y avoir des moments où les deux décompositions pour un appel d'opérateur sont valides, vous pouvez avoir des problèmes ici et nous différerons cette conversation.
Enfin, notez à quel point il peut être étrange d'écrire un opérateur membre unaire censé ressembler à un opérateur binaire (car vous pouvez rendre les opérateurs membres virtuels ..... en essayant également de ne pas dévoluer et de suivre ce chemin .... )
Cette syntaxe va maintenant irriter de nombreux codeurs ...
Remarquez comment le
cout
deuxième argument de la chaîne est ici ... étrange, non?la source