2011-12-04 5 views
10

quiero sobrecargar el operador < < en una de mis clases. La firma es la siguiente:C++: ¿las funciones de amigo deben estar definidas en el archivo de encabezado?

friend std::ostream& operator<<(std::ostream& os, const Annuaire& obj) 

Cuando trato de definirlo en el .cpp presentar dice que el operador < < toma exactamente 1 argumento, sin embargo, cuando me defino en el .h, se compiló /funciona bien.

Éste es cómo definirlo en el archivo .cpp:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... } 

¿Tiene algo que ver con funciones amigas que necesitan ser definidos en los archivos de cabecera?

+0

Tienes que '' ostream' y istream' derecha ... –

+0

sí, su amigo es istream y el de la CPP es ostream, si eso es intencional, se necesitan 2 declaraciones amigo y 2 definiciones , si no, corrige una u otra dependiendo de si quieres dentro o fuera de la corriente –

+0

Gracias, eso fue un error de copiar y pegar de todos modos. – Pacane

Respuesta

9

Puede ser definido en un fichero cpp, pero tiene que ser por lo menos declaró en un fichero de cabecera, de lo contrario todos los lugares donde se desee utilizar sólo será vea las cosas que le da la transmisión en sí, no su sobrecarga.

// .h and in class 
friend std::ostream& operator<<(std::ostream& os, MyClass const& v); 

// .cpp 
std::ostream& operator<<(std::ostream& os, MyClass const& v){ 
    // print it 
} 
2

No tal restricción; Probablemente lo estés escribiendo mal. Debe ser algo como esto:

class Foo 
{ 
    int n; 

    friend std::ostream & operator<<(std::ostream &, Foo const &); 
}; 

std::ostream & operator<<(std::ostream & o, Foo const & x) 
{ 
    return o << x.n; 
} 
9

El problema está en la forma en que lo está definiendo. No es un miembro de de la clase, que es sólo un amigo de la clase. Debe soltar el prefijo Annuaire::. Por lo tanto, cambiar esta situación:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... 

a esto:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj){ // ... 

La razón para el mensaje de error es que Annuaire::operator<<(std::ostream& os, const Annuaire& obj) esperaría tres argumentos: la instancia Annuaire que se llama el (como this), yy dos argumentos adicionales (os y obj).

3

Las funciones de amigo, incluso si parecen que se declararán dentro de la clase no son funciones miembro sino más bien funciones de nivel de espacio de nombres (en el espacio de nombres adjunto). En su código declara la función amigo correctamente, pero intenta definirlo como una función miembro de la clase:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ 

Esta definición sería para una función miembro de Annuaire, llamado operator<<, que toma dos argumentos, que es válido como operator<< puede sobrecargarse en una de dos maneras: como una función libre de tomar dos argumentos (lado izquierdo y lado derecho) o como una función miembro de la clase que aparece en la izda de la expresión de tomar un argumento de el tipo de rhs. En este caso particular, ya que los lhs es std::ostream y no se puede modificar, lo que queda es la única opción de usar una función libre:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj) 
+0

+1 para agregar una nota en el espacio de nombres adjunto. Agregar 'using namespace X' antes de la definición de la función real no es suficiente. – moooeeeep

2

Como se mencionó en la respuesta de David, en este caso el operador no es una función de miembro, es simplemente una función de amigo en el mismo espacio de nombres. Esto me apuntó en la dirección correcta al resolver un problema muy similar.

Estoy publicando esta respuesta porque no fue inmediatamente obvio para mí. Tal vez porque el archivo de implementación donde estaba agregando el operador no estaba completamente encerrado en el espacio de nombres, y usó una directiva de uso en su lugar.

No debería ser relevante, pero estoy usando VS2013.

//Foo.h 
namespace Bar{ 
    class Foo 
    { 
    public: 
     Foo(); 
    private: 
     int n; 
     friend std::ostream & operator<<(std::ostream &, Foo const &); 
    }; 
} 

//Foo.cpp 
using namespace Bar; //won't apply to the operator definition 
Foo::Foo(){}// doesn't require the Bar qualifier because of the using-directive 

//the operator required the Bar namespace qualifier 
std::ostream & Bar::operator<<(std::ostream & o, Foo const & x) 
{ 
    return o << x.n; 
} 
+0

¡Exactamente mi problema! Aunque no estoy muy seguro de por qué está pasando esto. – Flynsee

Cuestiones relacionadas