Sobrecarga de Operadores en C++ Informática II Fundamentos de Programación Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 1 Sobrecarga de Operadores • Los operadores, al igual que las funciones, pueden ser sobrecargados (overloaded): overloaded): – La mayor parte de los operadores de C++ pueden ser redefinidos para actuar sobre objetos de una clase. – Se puede cambiar la definición de un operador, pero no su gramática: nº de operandos, precedencia y asociatividad. – El tipo de los operandos determina qué definición del operador se va a utilizar. – Al menos uno de los operandos debe ser un objeto de la clase. • La sintaxis para declarar un operador sobrecargado es la siguiente: siguiente: tipo operator operador([argumentos]); Donde: tipo indica el tipo del valor retornado por la función, y operador es unos de los siguientes: +,-,*,/,%,&,!,>,<,=,[],new, delete, ... class Complejo { private: float real, imag; public: Complejo(float x, float y){ real=x; imag=y; } Complejo operator+( Complejo c); void Print(); }; Complejo Complejo::operator+(Complejo c) { return Complejo(real + c.real,imag + c.imag); } void main() { Complejo c1(1.5,4.5); Complejo c2(-2,-1); Complejo c3 = c1+c2; //= c3=c1.operator+(c2); c3.Print(); } Ejercicio, sobrecargar el operador de multiplicación: (a+bi)*(c+di) = a*c – b*d, a*d+b*ci Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 2 Sobrecarga de Operadores • Sobrecarga del operador de indexación “[ ]“: – El operador de indexación, operator [], permite manipular los objetos de clases igual que si fuesen arrays. – La llamada a la función operator[] de una clase se hace escribiendo el nombre de un objeto de la clase para el cual se quiere invocar dicha función, seguido de un valor encerrado entre corchetes. – La forma de sobrecargar el operador es: int& operator[]( int i); class Vector { private: int *pV; //puntero al 1 elemento int num; //num de elementos public: Vector( int ); //constr. ~Vector(){ delete [] pV; } int& operator[]( int i); }; Vector::Vector(int ne=1) //por defecto 1 { num = ne; pV = new int[num]; } int& Vector::operator [](int i) { return pV[i]; } void main() { int num; cout << "Numero:"; cin>>num; Vector v1(num); //llenar for (int i=0;i<num;i++) v1[i] = rand(); //imprime for ( i=0;i<num;i++) { cout << "i:"<<i<<" Val:" cout << v1[i] << endl; } } Hay que diferenciar que v1 no es un array de objetos. Cuando hacemos v1[i] estamos invocando a la función miembro v1.operator[](i). Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 3 Sobrecarga de operadores • Los operadores pueden definirse como miembros o como friends de una clase: – En los operadores friend el número de argumentos debe ser el estándar del operador. – Para los operadores miembro de una clase, el primer operando debe ser siempre un objeto de la clase. En la declaración y definición sólo hace falta definir el segundo argumento. – Los operadores que modifican el primer operando se suelen declarar como miembros. – Los operadores que no modifican los operandos suelen ser declarados como friend. – Los operadores de asignación (=, +=, -=, …), deben ser sobrecargados por funciones miembro. class Complejo { private: float real; float imag; public: Complejo(float x=0, float y=0){ real=x; imag=y; } Complejo operator+( Complejo c); friend bool operator==(Complejo c1,Complejo c2); friend bool operator<(Complejo, Complejo); double mod(){ return sqrt(real*real + imag*imag); } void Print(); }; bool operator<(Complejo c1, Complejo c2) { return c1.mod() < c2.mod(); } //funcion amiga. Operador de relacion bool operator==(Complejo c1, Complejo c2) { if (c1.real==c2.real&&c1.imag==c2.imag) return true; else return false; } void main() { Complejo c1(1.5,4.5); Complejo c2(1.5,4.5); if (c1 == c2) cout << "Son iguales"; else cout << "Son diferentes"; (c1<c2)? cout<<“Menor”: cout<< “No menor”; } Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 4 Sobrecarga de operadores • Sobrecarga del operador de inserción “<<“: – C++ tiene una clase denominada ostream definida con el operador << para la salida de valores de tipos predefinidos (int, long, double, etc..). class ostream { //... public: //.. ostream &operator<<(int); ostream &operator<<(double); }; – La función operator<< retorna una referencia al objeto de tipo ostream que llamó, para que éste pueda ser aplicado a otro valor: cout << f1 << f2; – Una forma sencilla de sobrecargar el operador << es implementar una función miembro amiga (friend) de esta clase, que tenga la siguiente forma: friend ostream &operator<<(ostream &os, clase_usuario &c); Donde os es una referencia a un objeto tipo ostream, en nuestro caso cout y c es una referencia a una clase del usuario que se desea visualizar. En el cuerpo de la función irá una expresión de la siguiente forma: os << valor1 << valor2 << valor3; ostream &operator<<(ostream &os,Complejo &c) { return ( os << "(" << c.r << "," << c.i << ")" ); } Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 5 Sobrecarga de operadores • Sobrecarga del operador de extracción “>>”: – C++ tiene una clase denominada istream definida con el operador >> para la entrada de valores de tipos predefinidos (int, long, double, etc..). class istream { //... public: //.. istream &operator>>(int); istream &operator>>(double); }; – La función operator>> retorna una referencia al objeto de tipo ostream que llamó, para que éste pueda ser aplicado a otro valor: cin >> f1 >> f2; – Una forma sencilla de sobrecargar el operador >> es implementar una función miembro amiga (friend) de esta clase, que tenga la siguiente forma: friend istream &operator>>(istream &is, clase_usuario &c); Donde is es una referencia a un objeto tipo istream, en nuestro caso cin y c es una referencia a una clase del usuario que se desea visualizar. En el cuerpo de la función irá una expresión de la siguiente forma: is >> valor1 >> valor2 >> valor3; istream &operator>>(istream &is,Complejo &c) { cout << "Escriba un complejo:"; return (is >> c.r >> c.i); } Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 6 #include <iostream.h> void main() { Complejo c1(3,4); Complejo c2(-2,1); Complejo c3(1,-2); class Complejo { private: float r,i; public: Complejo(float pr=0, float pi=0){ r=pr; i=pi; } Complejo operator+(Complejo c); Complejo operator-(Complejo c); friend ostream &operator<<(ostream &os, Complejo&); friend istream &operator>>(istream &is, Complejo&); void Print(){ cout << r << "," << i << "i\n"; } }; } Complejo Complejo::operator +(Complejo c) { return Complejo(r+c.r,i+c.i); } Complejo Complejo::operator -(Complejo c) { return Complejo(r-c.r,i-c.i); } ostream &operator<<(ostream &os,Complejo &c) { return ( os << "(" << c.r << "," << c.i << ")" ); } istream &operator>>(istream &is,Complejo &c) { cout << "Escriba un complejo:"; return (is >> c.r >> c.i); } Complejo r = c1+c2+c3; r.Print(); // operadores Complejo n,n1; cin >> n >> n1; cout << “Los complejos son: “; cout << n << "-“ <<n1; Escuela Superior de Ingenieros de San Sebastián - Tecnun Tecnun 7