2010-05-13 14 views
18

En un proyecto en el que estoy trabajando, tengo una clase Score, definida a continuación en score.h. Estoy intentando sobrecargarlo, así que, cuando se realiza una operación <<, se imprime _points + " " + _name.funciones 'amigo' y << sobrecarga del operador: ¿Cuál es la forma correcta de sobrecargar a un operador para una clase?

Esto es lo que he intentado hacer:

ostream & Score::operator<< (ostream & os, Score right) 
{ 
    os << right.getPoints() << " " << right.scoreGetName(); 
    return os; 
} 

Éstos son los errores devueltos:

score.h(30) : error C2804: binary 'operator <<' has too many parameters 

(Este error aparece 4 veces, en realidad)

me las arreglé para conseguir que funcione al declarar la sobrecarga como una función amiga:

friend ostream & operator<< (ostream & os, Score right); 

Y eliminando el Score:: de la declaración de función en score.cpp (de hecho no lo declara como miembro).

¿Por qué funciona esto, sin embargo, la antigua pieza de código no?

¡Gracias por su tiempo!

EDITAR

He eliminado todas las menciones a la sobrecarga en el archivo de cabecera ... todavía tengo la (y único) de error siguiente. binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion) ¿Cómo es que mi prueba, en main(), no puede encontrar la sobrecarga adecuada? (No se incluye el, he comprobado)

A continuación se muestra la score.h completa

#ifndef SCORE_H_ 
#define SCORE_H_ 

#include <string> 
#include <iostream> 
#include <iostream> 

using std::string; 
using std::ostream; 

class Score 
{ 

public: 
    Score(string name); 
    Score(); 
    virtual ~Score(); 
    void addPoints(int n); 
    string scoreGetName() const; 
    int getPoints() const; 
    void scoreSetName(string name); 
    bool operator>(const Score right) const; 

private: 
    string _name; 
    int _points; 

}; 
#endif 

Respuesta

54

Nota: Es posible que desee ver el operator overloading FAQ.


operadores binarios pueden ser o bien miembros de la clase de su argumento de la izquierda o funciones gratuitas. (Algunos operadores, como la asignación, deben ser miembros). Dado que el argumento de la izquierda de los operadores de flujo es una secuencia, los operadores de flujo deben ser miembros de la clase de flujo o de las funciones gratuitas. La forma canónica para implementar operator<< para cualquier tipo es la siguiente:

std::ostream& operator<<(std::ostream& os, const T& obj) 
{ 
    // stream obj's data into os 
    return os; 
} 

en cuenta que es no una función miembro. También tenga en cuenta que lleva el objeto a la transmisión por referencia const. Esto se debe a que no desea copiar el objeto para poder transmitirlo y tampoco desea que la transmisión lo altere.


veces que desea transmitir objetos cuyas partes internas no son accesibles a través de su clase interfaz pública, por lo que el operador no puede llegar a ellos.Entonces usted tiene dos opciones: o bien poner un miembro del público en la clase que hace la transmisión

class T { 
    public: 
    void stream_to(std::ostream&) const {os << obj.data_;} 
    private: 
    int data_; 
}; 

y llamar a que desde el operador:

inline std::ostream& operator<<(std::ostream& os, const T& obj) 
{ 
    obj.stream_to(os); 
    return os; 
} 

o hacer que el operador de un friend

class T { 
    public: 
    friend std::ostream& operator<<(std::ostream&, const T&); 
    private: 
    int data_; 
}; 

para que pueda acceder a las partes privadas de la clase:

inline std::ostream& operator<<(std::ostream& os, const T& obj) 
{ 
    os << obj.data_; 
    return os; 
} 
+0

Agradable, respuesta completa. –

+0

Acceda a las partes privadas de la clase: Rawr. J/K, muchas gracias, todavía queda una pregunta: Eliminé todas las menciones de la sobrecarga en el archivo de encabezado ... pero me sale el siguiente (y único) error. 'binary '<<': no ​​se encontró operador que tome un operando de la derecha del tipo 'Score' (o no hay una conversión aceptable)' ¿Cómo es que mi prueba, en main(), no puede encontrar el ¿sobrecarga? (no es el incluye). –

+1

Debe poner la declaración del 'operator <<' right con la definición de su clase: que está en el mismo encabezado y en el mismo espacio de nombres. De esta forma, no se olvidará de incluirlo y el compilador podrá recogerlo cuando busque sobrecargas aceptables. –

9

Digamos que quería escribir una sobrecarga del operador para + por lo que podría añadir dos Score objetos entre sí, y la otra por lo que podría añadir una int a un Score, y un tercero por lo que podría añadir un Score a un int . Aquellos en los que un Score es el primer parámetro pueden ser funciones miembro de Score. Pero aquel en el que int es el primer parámetro no puede convertirse en funciones miembro de int, ¿verdad? Para ayudarte con eso, puedes escribirlos como funciones gratuitas. Eso es lo que está sucediendo con este operador <<, no puede agregar una función de miembro a ostream para que escriba una función gratuita. Eso es lo que significa cuando quitas la parte Score::.

Ahora, ¿por qué tiene que ser un friend? No es así Solo está llamando a métodos públicos (getPoints y scoreGetName). Ves muchos amigos operadores porque les gusta hablar directamente con las variables privadas. Estoy bien que lo haga, porque la persona que mantiene la clase la escribe y la mantiene. Simplemente no mezcle parte del amigo con la parte miembro función-vs-función libre.

+0

¡Gracias por la entrada extra! –

6

que está recibiendo errores de compilación cuando operator<< es una función miembro en el ejemplo, porque va a crear un operator<< que toma un Score como primer parámetro (el objeto de ser el método llamado sucesivamente), y luego lo que le da un extra parámetro al final.

Cuando llamas a un operador binario que está declarado como función miembro, el lado izquierdo de la expresión es el objeto al que se llama el método. p.ej. a + b poder funciona así:

A a; 
B b 

a.operator+(b) 

Es normalmente preferible utilizar los operadores binarios que no son miembros (y en algunos casos - por ejemplo operator<< para ostream es la única manera de hacerlo En ese caso, a + b podría funcionar similares. esto:

A a; 
B b 

operator+(a, b); 

Aquí hay un ejemplo completo que muestra ambas formas de hacerlo; main() hará salir '55' en tres ocasiones:

#include <iostream> 

struct B 
{ 
    B(int b) : value(b) {} 
    int value; 
}; 


struct A 
{ 
    A(int a) : value(a) {} 
    int value; 

    int operator+(const B& b) 
    { 
     return this->value + b.value; 
    } 
}; 

int operator+(const A& a, const B& b) 
{ 
    return a.value + b.value; 
} 

int main(int argc, char** argv) 
{ 
    A a(22); 
    B b(33); 

    std::cout << a + b << std::endl; 
    std::cout << operator+(a, b) << std::endl; 
    std::cout << a.operator+(b) << std::endl; 

    return 0; 
} 
Cuestiones relacionadas