Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Sobrecarga de Operadores • El usuario puede darle nuevos significados a operadores existentes en el lenguaje • Los tipos de operadores son: 3.5 Sobrecarga de Operadores en C++ – Arímeticos, lógicos y relacionales – Llamada a función () – Subíndice [] – Desreferenciación – Asignación e inicialiazación 1 III-2 Departamento de Informática Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Ejemplo Sencillo Operadores que se Sobrecargan class complejo { double re, im ; public: complejo(double r, double i) {re=r; i m=i;} friend complejo operator+ (complejo, complejo); friend complejo operator* (complejo, complejo); // … }; void f() { complejo a(3.4, 2.6); complejo b(4.5, 2.7); complejo c(1.0, 1.0); a = b + c; Lenguajes de Programación Universidad Técnica Federico Santa María + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new delete // equivale a: a = operator (b, c) } III-3 Departamento de Informática Universidad Técnica Federico Santa María III-4 Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Operadores Binarios Operadores Unarios • Para el operador binario @, a@b puede interpretarse como: • Para el operador unario prefijo @, @a puede interpretarse como: a.operator@ () operator@ (a) a.operator@ (b) operator@ (a, b) Lenguajes de Programación // función miembro // función global // función miembro // función global • Para el operador unario posfijo @, a@ puede interpretarse como: a.operator@ (int) // función miembro operator@ (a, int) // función global • Sintaxis determina operadores unarios aceptados III-5 III-6 Departamento de Informática Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Universidad Técnica Federico Santa María Ejemplo class X // operan con implícitamente con ´this´ X* operator& (); // & prefijo unario (dirección) X operator & (X) // & binario ( and) X operator ++ (int ); // incremento postfijo X operator & (X, X); // ERROR: no permite ternario X operator / (); // ERROR: unario / no existe }; // funciones globales (gralmente son amigas de alguna clase) X X X X X X operator- (X); operator- (X, X) operator-- (X&, int ); operator- (); operator- (X, X, X); operator% (X); // // // // // // - prefijo unario - binario decremento postfijo ERROR: sin operandos ERROR: no permite ternario ERROR: unario % no existe Lenguajes de Programación Observaciones al Significado de Operadores Sobrecargados • No es posible inferir significados especiales al sobrecargar operadores – e.g.: a += b no permite inferir a = a+b • Operadores de asignación =, dirección & y secuenciación “,” tienen significados especiales al aplicarlos a clases • Un función operador debe ser miembro o tomar como primer argumento un objeto de una clase declarada III-7 Departamento de Informática Universidad Técnica Federico Santa María III-8 Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Objetos Grandes (1/2) Lenguajes de Programación Objetos Grandes (2/2) class matriz { double m[MAX][MAX]; public: matriz(); matriz operador+ (const matriz&); // … }; class matriz { double m[MAX][MAX]; public: matriz(); matriz& operador+ (const matriz&); // … }; matriz matriz::operator+ ( const matriz& a) { matriz suma; for ( int i =O; i<MAX; i++) for ( int j =O; j<MAX; j++) suma.m[i][j] = m[i][j] + a.m[i][j]; return suma; } matriz& matriz:: operator + (const matriz& a) { matriz suma; for ( int i =O; i<MAX; i++) for ( int j =O; j<MAX; j++) suma.m[i][j] = m[i][j] + a.m[i][j]; return suma; } ¡Implica copiar suma en el retorno! ¡Más eficiente, pero retorna referencia al stack! III-9 Departamento de Informática Universidad Técnica Federico Santa María III-10 Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Problema de Asignación Lenguajes de Programación Sobrecarga de la Asignación class string { char* p; int size ; public: string(int s) { p = new char[size=s};} string& operator= (const string&); // asignación ~string() { delete[] p; } }; class string { char* p; int size; public: string(int s) { p = new char[size=s};} ~string() { delete[] p; } }; void f() { string s1(10); string s2(20); s1 = s2; // oops … se genera basura } // oops… se destruye dos veces el mismo string ¡Una asignación no declarada produce copia al bit de los objetos! (como sucede con estructuras) III-11 string& string :: operator = (const& s) { if (this != &s) { // atención con s=s delete [] p; p = new char[size = s .size ]; strcpy (p, s.p); } return * this; } III-12 Departamento de Informática Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Universidad Técnica Federico Santa María Problema con Inicialización Constructor de Inicialización • Para un tipo X, el constructor X(const X&) realiza inicialización con objeto del mismo tipo // usando última versión de string void f() { string s1(10); string s2 = s1; ... } Lenguajes de Programación class string { char* p; int size; public: string(int s) { p = new char[size=s};} string(const string&); // inicialización string& operator= (const string&); // asignación ~string() { delete[] p; } }; // oops .. = es inicialización // ∴ NO llama a la asignación // oops … destruye dos veces el mismo string ¡Una inicialización no declarada produce copia al bit de los objetos! (como sucede con estructuras) string::string(const string& s) { p= new char[size=s.size]; strcpy(p, s.p); } III-13 Departamento de Informática Universidad Técnica Federico Santa María III-14 Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Lenguajes de Programación Ejemplo: Operador [](1/4) Operador de Subíndice • El operador [] puede ser sobrecargado • El tipo de dato que se use en el subíndice puede ser de cualquier tipo (no necesariamente entero) • Una aplicación interesante es para definir arreglos asociativos (acceso por contenido) class asoc { struct par { char* nombre; int valor; }; par* ar; // arreglo asociativo int max; // tamaño máximo del arreglo int libre; // posición de primero libre asoc (const asoc&); // impide copia de inic. asoc& operator= (const asoc&);// impide copia de asig. public: asoc (int); int& operator[] (const char*); void imprimir(); ~asoc (); }; III-15 Departamento de Informática Universidad Técnica Federico Santa María III-16 Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Lenguajes de Programación Ejemplo: Operador [] (3/4) Ejemplo: Operador [] (2/4) int& asoc::operator[] (const char* s) { register par* pp; // constructor for (pp=&ar[libre-1]; ar <= pp; pp--) if(strcmp(s, pp->nombre) == 0) return pp->valor; asoc::asoc (int i) { max = (i<16) ? 16 : i; libre = 0; ar = new par[max]; } // no se encontró en el arreglo if (libre == max) { // arreglo agotado par* vec = new par[max*2]; for (int i=0; i<max; i++) vec[i] = ar[i]; delete[] ar; ar = vec; max *= 2; } // ahora si que hay espacio para el nuevo string pp = &ar[libre++]; // pp apunta a primero libre pp->nombre = new char[strlen(s) +1]; strcpy(pp->nombre, s); pp->valor = 0; // valor inicial en 0 return pp->valor; // destructor asoc::~asoc () { delete[] ar; } III-17 } III-18 Departamento de Informática Universidad Técnica Federico Santa María Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María Ejemplo: Operador [] (4/4) Lenguajes de Programación Operador de Función int& asoc::imprimir () { for (int i=0; i<libre; i++) cout << ar[i].nombre << “:” << ar[i].valor << “\n”; } // el programa cuenta las palabras que se ingresan // y luego imprime las estadísticas main () { const MAX = 256; char palabra[MAX]; asoc aa(512); • El operador () puede ser sobrecargado • Es útil para definir tipos con una única operación, o una que es predominante • Una aplicación es para la definición de iteradores while (cin >> palabra) aa[palabra]++; aa.imprimir(); } III-19 Departamento de Informática Universidad Técnica Federico Santa María Ejemplo : Iterador III-20 Departamento de Informática Lenguajes de Programación Universidad Técnica Federico Santa María (1/2) Lenguajes de Programación Ejemplo : Iterador class asoc { friend class iterador_asoc; par* ar; // arreglo de pares asociados int max; // tamaño máximo del arreglo int libre; // posición de primero libre public: asoc (int); int& operator[] (const char*); }; class iterador_asoc { const asoc* aa; // arreglo asociativo int i // indice actual en el arreglo public: iterador_asoc (const asoc& a) { aa = &a; i=0; } par* operador() () // sobrecarga llamada afunción { return (i < aa->libre)? aa->ar[i++] : 0; } }; III-21 (2/2) // el programa cuenta las palabras que se ingresan // y luego imprime las estadísticas main () { const MAX = 256; char palabra[MAX]; asoc aa(512); while (cin >> palabra) aa[palabra]++; // imprimir las estadísticas iterador_asoc proximo_par(aa); par* p; while (p = proximo_par()) cout << p->nombre << “:” << p->valor << “\n”; } III-22