a.h
#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, ça dit:
std :: ostream & logic :: operator << (std :: ostream &, A &) 'doit prendre exactement un argument.
Quel est le problème?
Le problème est que vous le définissez dans la classe, ce qui
a) signifie que le deuxième argument est implicite (this
) et
b) il ne fera pas ce que vous voulez, à savoir étendre std::ostream
.
Vous devez le définir comme une fonction libre:
class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);
Une fonction ami n'est pas une fonction membre. Le problème est que vous déclarez operator<<
en tant qu'ami de A
:
friend ostream& operator<<(ostream&, A&);
puis essayez de le définir en tant que fonction membre de la classe logic
ostream& logic::operator<<(ostream& os, A& a)
^^^^^^^
Êtes-vous confus quant à savoir si logic
est une classe ou un espace de noms?
L'erreur est due au fait que vous avez essayé de définir un membre operator<<
en prenant deux arguments, ce qui signifie qu'il faut trois arguments, y compris le paramètre implicite this
. L'opérateur ne peut prendre que deux arguments. Ainsi, lorsque vous écrivez a << b
, les deux arguments sont a
et b
.
Vous voulez définir ostream& operator<<(ostream&, const A&)
en tant que fonction non - membre, certainement pas en tant que membre de logic
car cela n’a rien à voir avec cette classe!
std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << a.number;
}
J'ai rencontré ce problème avec les classes basées sur des modèles ..__ Voici une solution plus générale que je devais utiliser:
template class <T>
class myClass
{
int myField;
// Helper function accessing my fields
void toString(std::ostream&) const;
// Friend means operator<< can use private variables
// It needs to be declared as a template, but T is taken
template <class U>
friend std::ostream& operator<<(std::ostream&, const myClass<U> &);
}
// Operator is a non-member and global, so it's not myClass<U>::operator<<()
// Because of how C++ implements templates the function must be
// fully declared in the header for the linker to resolve it :(
template <class U>
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj)
{
obj.toString(os);
return os;
}
Maintenant: * Ma fonction toString () ne peut pas être en ligne si elle doit être cachée dans cpp . * Vous êtes coincé avec un code dans l'en-tête, je ne pouvais pas 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 comprends mal ou que je manque quelque chose, mais déclarer simplement le modèle d'opérateur ne crée pas de lien dans gcc.
Cela fonctionne aussi:
template class <T>
class myClass
{
int myField;
// Helper function accessing my fields
void toString(std::ostream&) const;
// For some reason this requires using T, and not U as above
friend std::ostream& operator<<(std::ostream&, const myClass<T> &)
{
obj.toString(os);
return os;
}
}
Je pense que vous pouvez également éviter les problèmes de gabarit imposant les déclarations dans les en-têtes, si vous utilisez une classe parent qui n'est pas modélisée pour implémenter l'opérateur << et utilisez une méthode toString () virtuelle.