282 votes

Comment surcharger correctement le << opérateur pour un ostream ?

Je suis en train d'écrire une petite bibliothèque de matrice en C++ pour les opérations matricielles. Cependant mon compilateur se plaint, là où auparavant il n'en avait pas. Ce code a été laissé sur une étagère pendant 6 mois et entre les deux j'ai mis à jour mon ordinateur à partir de debian etch à lenny (g++ (Debian 4.3.2-1.1) 4.3.2 ) cependant j'ai le même problème sur un système Ubuntu avec le même g++.

Voici la partie pertinente de ma classe matrix:

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
    }
}

Et la "mise en œuvre":

using namespace Math;

std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {

    [...]

}

C'est l'erreur donnée par le compilateur:

la matrice.rpc:459: erreur: 'std::ostream& Math::Matrice::operator<<(std::ostream&, const Math::Matrice&) " doit prendre exactement un argument

Je suis un peu confus par cette erreur, mais là encore mon C++ a eu un peu rouillé après avoir fait beaucoup de Java 6 mois. :-)

157voto

Juste vous raconter une autre possibilité: j'ai comme l'utilisation d'ami définitions:

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
            [...]
        }
    };
}

La fonction sera automatiquement ciblées dans l'espace de noms Math (même si sa définition apparaît dans le champ d'application de cette classe) mais ne sera pas visible sauf si vous appelez de l'opérateur<< avec une Matrice de l'objet qui fera de l'argument de référence dépendant de trouver que la définition de l'opérateur. Parfois ambiguës appels, car il est invisible pour les types d'argument autre que la Matrice. Lors de l'écriture de sa définition, vous pouvez aussi consulter directement les noms définis dans la Matrice et la Matrice elle-même, sans la qualifier du nom de certains peut-être long préfixe et de fournir des paramètres du modèle comme Math::Matrix<TypeA, N>.

145voto

Mehrdad Afshari Points 204872

Vous avez déclaré votre fonction en tant que . Il n’est pas un membre de la classe. Vous devez supprimer la de la mise en œuvre. signifie que la fonction spécifiée (ce qui n’est pas un membre de la classe) peut accéder aux variables de membre privé. La façon dont vous avez implémenté la fonction est comme une méthode d’instance de classe, ce qui est faux.

92voto

kal Points 5324

Pour ajouter à la réponse de Mehrdad,

Dans votre implémentation

80voto

sanjivr Points 306

En supposant que nous parlons à propos de la surcharge de l'opérateur << pour toutes les classes dérivées de std::ostream pour gérer la Matrice de la classe (et pas de surcharge de << pour la classe Matrix), il est plus judicieux de déclarer la fonction de surcharge à l'extérieur de la Mathématique de l'espace de noms dans l'en-tête.

Utilisez un ami de la fonction uniquement si la fonctionnalité ne peut pas être atteint via les interfaces publiques.

La matrice.h

namespace Math { 
      class Matrix { 
       ...
       };  
}
std::ostream& operator<< (std::ostream&, const Math::Matrix&);

Notez que l'opérateur de surcharge est déclarée en dehors de l'espace de noms.

Matrix.cpp

using namespace Math;
using namespace std;

ostream& operator<< (ostream& os, const Matrix& obj) {
       os << obj.getXYZ() << obj.getABC() << "\n";
       return os;
}       

D'autre part, si votre surcharge de fonction ne doivent être fait un ami que j'ai.e a besoin d'accéder aux membres privés et protégés

Les mathématiques.h

namespace Math {
     class Matrix {
          public:
             friend std::ostream& operator<< (std::ostream& , const Matrix&);
     };
}

Vous devez placer la définition de la fonction avec un espace de noms bloc au lieu de simplement "en utilisant un espace de Mathématiques;"

Matrix.cpp

using namespace Math;
using namespace std;

namespace Math {
   ostream& operator<< (ostream& os, const Matrix& obj) {
         os << obj.XYZ << obj.ABC << "\n";
         return os;
  }                 
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X