Pregunta

Estoy escribiendo una pequeña biblioteca matricial en C ++ para operaciones matriciales. Sin embargo, mi compilador se queja, donde antes no lo hacía. Este código se dejó en un estante durante 6 meses y en el medio actualicé mi computadora de debian etch a lenny (g ++ (Debian 4.3.2-1.1) 4.3.2 ) sin embargo, tengo el mismo problema en un sistema Ubuntu con el mismo g ++.

Aquí está la parte relevante de mi clase de matriz:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

Y la " implementación " ;:

using namespace Math;

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

    [...]

}

Este es el error dado por el compilador:

  

matrix.cpp: 459: error: 'std :: ostream & amp;   Matemáticas :: Matriz :: operador < < (std :: ostream & amp ;,   const Math :: Matrix & amp;) 'debe tomar   exactamente un argumento

Estoy un poco confundido por este error, pero de nuevo mi C ++ se ha oxidado un poco después de hacer mucho Java esos 6 meses. :-)

¿Fue útil?

Solución

Ha declarado su función como amigo . No es un miembro de la clase. Debe eliminar Matrix :: de la implementación. friend significa que la función especificada (que no es miembro de la clase) puede acceder a variables de miembros privados. La forma en que implementó la función es como un método de instancia para la clase Matrix que está mal.

Otros consejos

Solo te cuento sobre otra posibilidad: me gusta usar definiciones de amigos para eso:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

La función se dirigirá automáticamente al espacio de nombres circundante Math (aunque su definición aparezca dentro del alcance de esa clase) pero no será visible a menos que llame al operador < < con un objeto Matrix que hará que la búsqueda dependiente del argumento encuentre esa definición de operador. Eso a veces puede ayudar con llamadas ambiguas, ya que es invisible para los tipos de argumento que no sean Matrix. Al escribir su definición, también puede referirse directamente a los nombres definidos en Matrix y a Matrix, sin calificar el nombre con algún prefijo posiblemente largo y proporcionar parámetros de plantilla como Math :: Matrix < TypeA, N > .

Para agregar a la respuesta de Mehrdad,

namespace Math
{
    class Matrix
    {
       public:

       [...]


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

En su implementación

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

Suponiendo que estamos hablando de sobrecargar el operador < < para todas las clases derivadas de std :: ostream para manejar la Matrix clase (y no sobrecargar < < para la clase Matrix ), tiene más sentido declarar la función de sobrecarga fuera del espacio de nombres matemático en el encabezado.

Use una función amiga solo si la funcionalidad no se puede lograr a través de las interfaces públicas.

Matrix.h

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

Tenga en cuenta que la sobrecarga del operador se declara fuera del espacio de nombres.

Matrix.cpp

using namespace Math;
using namespace std;

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

Por otro lado, si su función de sobrecarga necesita hacerse amigo, es decir, necesita acceso a miembros privados y protegidos.

Math.h

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

Necesita encerrar la definición de la función con un bloque de espacio de nombres en lugar de simplemente usando el espacio de nombres 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 puede usar la siguiente plantilla para imprimir cualquier objeto que tenga un T :: print (std :: ostream & amp;) const; miembro.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top