2012-10-09 27 views
21

Estoy intentando anular el operador << para una clase. El objetivo es básicamente implementar un comportamiento similar a toString() para mi clase, de modo que enviarlo a cout producirá resultados útiles. Usando un ejemplo ficticio, tengo el siguiente código. Cuando intento compilar, obtengo el siguiente error:C++ múltiples definiciones de operador <<

$ g++ main.cpp Rectangle.cpp 
/tmp/ccWs2n6V.o: In function `operator<<(std::basic_ostream<char, std::char_traits<char> >&, CRectangle const&)': 
Rectangle.cpp:(.text+0x0): multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, CRectangle const&)' 
/tmp/ccLU2LLE.o:main.cpp:(.text+0x0): first defined here 

No puedo entender por qué sucede esto. mi código es el siguiente:

Rectangle.h:

#include <iostream> 
using namespace std; 

class CRectangle { 
    private: 
     int x, y; 
     friend ostream& operator<<(ostream& out, const CRectangle& r); 
    public: 
     void set_values (int,int); 
     int area(); 
}; 

ostream& operator<<(ostream& out, const CRectangle& r){ 
    return out << "Rectangle: " << r.x << ", " << r.y; 
} 

Rectangle.cpp:

#include "Rectangle.h" 

using namespace std; 

int CRectangle::area(){ 
    return x*y; 
} 

void CRectangle::set_values (int a, int b) { 
    x = a; 
    y = b; 
} 

main.cpp:

#include <iostream> 
#include "Rectangle.h" 

using namespace std; 

int main() { 
    CRectangle rect; 
    rect.set_values (3,4); 
    cout << "area: " << rect.area(); 
    return 0; 
} 

Respuesta

33

Estás rompiendo la definición uno regla. Una solución rápida es:

inline ostream& operator<<(ostream& out, const CRectangle& r){ 
    return out << "Rectangle: " << r.x << ", " << r.y; 
} 

Otros son:

  • declarar el operador en el archivo de cabecera y mover la aplicación a Rectangle.cpp archivo.
  • define el operador dentro de la definición de clase.

.

class CRectangle { 
    private: 
     int x, y; 
    public: 
     void set_values (int,int); 
     int area(); 
     friend ostream& operator<<(ostream& out, const CRectangle& r){ 
      return out << "Rectangle: " << r.x << ", " << r.y; 
     } 
}; 

bonificación:

  • uso incluyen guardias
  • quitan el using namespace std; de la cabecera.
+0

* En el caso de la definición del miembro: * Si hay otra definición de clase por encima de la 'CRectangle' y en el' '<< sobrecarga usa el '<<' de 'CRectangle' luego hay problemas. ¡Incluso cuando se hace una declaración directa de 'CRectangle'! ¿Alguna idea de por qué? – Paschalis

10

Usted está poniendo la definiciónde una función en un archivo .h, lo que significa que va a aparecer en cada unidad de traducción, que viola la regla de un Definición (=> ha definido operator<< en cada módulo de objeto, por lo que la el enlazador no sabe cuál es "el correcto").

Puede:

  • escribir simplemente la declaración de su operador (es decir, su prototipo) en el archivo .h y mover su definición a rectangle.cpp
  • hacer operator<<inline - se permite inline funciones se definirá más de una vez, siempre que todas las definiciones sean idénticas.

(También, debería usar protectores de cabecera en las incluye.)