Sobrecarga de Operadores: material adaptado
de The cplusplus.com
tutorial
C++ incorpora la posibilidad de usar operadores estándares con instancias de sus propias clases además del uso común con tipos fundamentales. Por ejemplo:
int a, b, c;es perfectamente válido, dado que las variables son todas tipos fundamentales. Sin embargo, no es tan obvio que podemos efectuar la operación siguiente ( de hecho es incorrecto):
a = b + c;
struct { char product [50]; float price; } a, b, c;Lo que conduce a error es el uso del operador adición, que en principio no es válido entre tipos no fundamentales.
a = b + c;
Pero en C++, podemos hacer que objetos, instancias de tipos compuestos, como los previos pueden aceptar operadores que de otra manera no serían aceptados. Incluso es posible redefinir el efecto de operadores ya permitidos. La lista de operadores que puede ser sobrecargados es:
Para sobrecargar un operador, sólo necesitamos escribir una función miembro en la clase cuyo nombre es operator seguido por el signo del operador que queremos sobrecargar, siguiendo este prototipo:+ - * / = < > += -= *= /= << >>
<<= >>= == != <= >= ++ -- % & ^ ! |
~ &= ^= |= && || %= [] () new delete
type operator sign (parameters);Aquí tenemos un ejemplo que incluye el operador +. Vamos a sumar vectores bidimensionales a(3,1) y b(1,2). En este caso el resultado será (3+1,1+2) = (4,3).
// vectors: overloading operators example #include <iostream.h> class CVector { public: int x,y; CVector () {}; CVector (int,int); CVector operator + (CVector); }; CVector::CVector (int a, int b) { x = a; y = b; } CVector CVector::operator+ (CVector param) { CVector temp; temp.x = x + param.x; temp.y = y + param.y; return (temp); } int main () { CVector a (3,1); CVector b (1,2); CVector c; c = a + b; cout << c.x << "," << c.y; return 0; } |
4,3 |
No se confunda por el hecho de ver muchos CVector. Algunos son el nombre de la clase CVector y otros son nombre de una función con ese nombre (constructor y destructor).
La función operator+ de la clase CVector es la encargada de sobrecargar el operador aritmético +. Hay dos formas para llamar esta operación:CVector (int, int); // function name CVector (constructor) CVector operator+ (CVector); // function operator+ that returns CVector type
c = a + b;
c = a.operator+ (b);
Igual como una clase incluye por omisión un constructor de copia y constructor vacío, ésta también incluye un definición por defecto para el operador de asignación (=) entre dos instancias de la misma clase. Éste copia el contenido bit a bit de los miembros no estáticos del objeto de la derecha al de la izquierda. Por supuesto, podemos redefinir este operador con cualquier otra funcionalidad que se desee; por jemplo, copia en profundidad cuando se tienen miembros datos punteros o en otros casos podriamos desear la copia de sólo algunos datos miembros o atributos.
La sobrecarga de operadores no nos obliga a seguir el mismo significado matemático o usual del operador, aún así es recomendado (por consistencia e interpretación intuitiva). Por ejemplo, no es lógico usar el operador + para restar dos objetos u operador == para asignar ceros a un objeto, aún cuando esto es posible.
El prototipo de la función operator+ puede resultar obvio, pero para otros operadores pueden no serlo. Aquí se tiene una tabla que resume cómo declarar las diferentes funciones de sobrecarga (reemplace @ por el operador en cada claso):
Se puede ver en esta tabla que los operadores se pueden sobrecargar de dos formas: como funciones miembro de la clase del operando del lado izquierdo o como funciones globales. No hay diferencia en su uso, sin embargo hay que recordar que funciones no miembros de la clase no pueden acceder a los miembros private o protected de una clase a menos que la función global sea declarada friend en la clase.* donde a es un objeto de clase A, b es una instancia de clase B y c es instancia de calse C.
Expression Comentario
Operator (@) Function member Global function @a prefijo
+ - * & ! ~ ++ -- A::operator@() operator@(A) a@ postfijo
++ -- A::operator@(int) operator@(A, int) a@b infijo
+ - * / % ^ & | < > == != <= >= << >> && || , A::operator@(B) operator@(A, B) a@b infijo
= += -= *= /= %= ^= &= |= <<= >>= [ ] A::operator@(B) - a(b, c...) postfijo
() A::operator()(B, C...) - a->b infijo
-> A::operator->(B) -