Question

J'écris une petite bibliothèque de matrices en C ++ pour les opérations matricielles. Cependant mon compilateur se plaint, alors qu'avant il ne le faisait pas. Ce code a été laissé sur une étagère pendant 6 mois et entre les deux, j'ai mis à niveau mon ordinateur 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 de matrices:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

Et la "mise en oeuvre":

using namespace Math;

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

    [...]

}

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

  

matrix.cpp: 459: erreur: 'std :: ostream & amp;   Math :: Matrix :: operator < < (std :: ostream & amp ;,   const Math :: Matrix & amp;) 'doit prendre   exactement un argument

Cette erreur me laisse un peu perplexe, mais mon C ++ est un peu rouillé après avoir utilisé beaucoup de Java ces 6 mois. : -)

Était-ce utile?

La solution

Vous avez déclaré votre fonction en tant que ami . Ce n'est pas un membre de la classe. Vous devez supprimer Matrix :: de l'implémentation. ami signifie que la fonction spécifiée (qui n'est pas membre de la classe) peut accéder aux variables de membre privées. La façon dont vous avez implémenté la fonction est comme une méthode d’instance pour la classe Matrix qui est incorrecte.

Autres conseils

Je vous parle d'une autre possibilité: j'aime utiliser les définitions d'amis pour cela:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

La fonction sera automatiquement ciblée dans l'espace de nom environnant Math (même si sa définition apparaît dans l'étendue de cette classe), mais ne sera pas visible à moins que vous appeliez l'opérateur < < avec un objet Matrix qui rendra la recherche dépendante des arguments trouver cette définition d’opérateur. Cela peut parfois aider avec des appels ambigus, puisqu'il est invisible pour les types d'argument autres que Matrix. Lorsque vous écrivez sa définition, vous pouvez également vous référer directement aux noms définis dans Matrix et à Matrix lui-même, sans qualifier le nom avec un préfixe éventuellement long et en fournissant des paramètres de modèle tels que Math :: Matrix < TypeA, N > .

Pour ajouter une réponse à Mehrdad,

namespace Math
{
    class Matrix
    {
       public:

       [...]


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

Dans votre implémentation

std::ostream& operator<<(std::ostream& stream, 
                     const Math::Matrix& matrix) {
    matrix.print(stream); //assuming you define print for matrix 
    return stream;
 }

Supposons qu'il soit question de surcharger l'opérateur < < pour toutes les classes dérivées de std :: ostream afin de gérer la matrice class (et ne surchargez pas < < pour la classe Matrix ), il est plus logique de déclarer la fonction de surcharge en dehors de l'espace de nom Math dans l'en-tête.

Utilisez une fonction amie uniquement si cette fonctionnalité ne peut pas être réalisée via les interfaces publiques.

Matrix.h

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

Notez que la surcharge de l'opérateur 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;
}

Par contre, si votre fonction de surcharge doit être transformée en ami, c’est-à-dire qu’elle doit avoir accès aux membres privés et protégés.

Math.h

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

Vous devez inclure la définition de fonction dans un bloc d'espace de nom au lieu de simplement en utilisant l'espace de noms Math; .

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;
    }                 
}

En C ++ 14, vous pouvez utiliser le modèle suivant pour imprimer tout objet comportant un T :: print (std :: ostream & amp;) const; membre.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top