Vous êtes sur la page 1sur 12

Programación II.

Guía 7 1

Facultad: Ingeniería
Escuela: Computación
Asignatura: Programación II

Tema: Sobrecarga de Operadores.

Objetivos

ƒ Describir como redefinir (sobrecargar) operadores para que funcionen con nuevos tipos de
datos.
ƒ Diferenciar sobrecarga de operadores binarios y unarios.
ƒ Identificar cuando sobrecargar operadores.
ƒ Implementar programas en C++ que sobrecarguen operadores unarios.

Materiales y Equipo

• Computadora con el software DevC++


• Guía Número 7

Introducción

Recordemos que los operadores son un tipo de tokens que indican al compilador la realización
de determinadas operaciones sobre variables u otros objetos (los operandos).
Por ejemplo, cuando encontramos una expresión del tipo:
z = x + y; // suponemos que x, y, z son de tipo int (1)

Sabemos que la sentencia contiene dos operadores; el de suma (+) y el de asignación (=); que
estos operadores actúan (operan) sobre objetos de tipo int, y que sus reglas de uso y su
significado (que resultados se obtienen) están perfectamente definidos en el lenguaje.
Los operadores aceptan uno o varios operandos de tipo específico (alguno de los tipos básicos
preconstruidos en el lenguaje), produciendo y/o modificando un valor de acuerdo con ciertas
reglas.
Sin embargo, C++ permite redefinir la mayor parte de ellos. Es decir, permite que puedan
aceptar otro tipo de operandos (distintos de los tipos básicos) y seguir otro comportamiento, al
2 Programación II, Guía 7
tiempo que conservan el sentido y comportamiento originales cuando se usan con los
operandos normales.
Esta posibilidad, que recibe el nombre de sobrecarga del operador, es una consecuencia del
polimorfismo y hace posible que en la expresión:
c = d + e; // suponemos que c, d, e son de tipo UnaClase (2)

el sentido de la suma y el de asignación sean totalmente específicos y distintos que el de la


expresión “1” anterior cuando se utilizaron los mismos operadores con operandos tipo int.

NOTA: La primera e importantísima advertencia es que la sobrecarga se refiere y tiene


aplicación solo cuando los operandos son instancias de clases. Es decir, no es posible
modificar el sentido de la suma y asignación de la expresión “2” si c, d y e fuesen enteros o de
cualquiera de los tipos básicos preconstruidos en el lenguaje.

La sobrecarga de los operadores es una de las características más interesantes de C++ y,


naturalmente, de la programación orientada a objetos.
La sobrecarga hace posible manipular objetos de clases con operadores estándar tales como
+, *, [ ] y <<.
Esta propiedad de los operadores permite redefinir el lenguaje C++, que puede crear nuevas
definiciones de operadores,
La sobrecarga es una característica que ofrece el lenguaje C++ para aplicar una misma
operación, a través de operadores o funciones, a diferentes tipos de datos.
Se pueden sobrecargar los operadores predefinidos y funciones definidas por el usuario.
La sobrecarga permite generalizar el uso de operadores y funciones.

Sobrecarga de Operadores.
Es el proceso de asignar dos ó más operaciones al mismo operador.
En otras palabras, permite asignar una o más funciones adicionales a un operador estándar,
con el fin de que ésta sea llamada según el contexto en el cual se utilice el operador.
Un operador sobrecargado no puede tener parámetros predeterminados.
Para sobrecargar un operador, y aplicarlo en operaciones entre clases, se usa la función
especial operador.
Una función operador es una función cuyo nombre consta de la palabra reservada operator
seguida de un operador unitario o binario que se sobrecargará.
Programación II. Guía 7 3
La sintaxis para sobrecargar un operador es la siguiente:
<tipo de dato> <Nombre de clase> operator <#> (lista de parámetros)
{ //instrucciones que forman el cuerpo del operador
}
Donde:
• tipo de dato: indica el tipo de dato que produce el operador sobrecargado, por lo
general es la referencia del objeto.
• Nombre de clase: es el nombre de clase en la que estamos aplicando sobrecarga.
• operator: es una palabra reservada utilizada para realizar la sobrecarga
• #: operador que estamos sobrecargando.
• Lista de parámetros: es la lista de objetos (en referencia) o variables que se
procesarán en la sobrecarga, si la operación es unaria no tendrá parámetros, si la
operación es binaria tendrá un parámetro.

Operadores sobrecargables.
El lenguaje C++ permite redefinir la funcionalidad de los siguientes operadores:
+ - * / % ^ & ~ ! = < > += -= *= /= %= ^= &= |= <<
>> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new new[] delete
delete[]

Los operadores +, -, * y & son sobrecargables en sus dos versiones, unaria y binaria.
Es decir: suma binaria +; más unitario +; multiplicación *; indirección *; referencia & y manejo
de bits &.
Es notable que C++ ofrezca casos de operadores sobrecargados incluso en su Librería
Estándar. Por ejemplo, los operadores == y != para la clase type_info.
Sin embargo, la posibilidad de sobrecarga no se extiende a todos los operadores.

Excepciones:
En la lista anterior, puede verificarse que todos los operadores pueden ser sobrecargados,
incluyendo new, new [ ], delete y delete [ ], excepto los siguientes:
• Selector directo de componente .
• Operador de indirección de puntero a miembro .*
• Operador de acceso a ámbito ::
• Condicional ternario ?:
4 Programación II, Guía 7
• Directivas de preprocesado # y # #
• sizeof: informa del tamaño de almacenamiento utilizado por cualquier objeto, sea un
tipo básico o derivado.
• typeid: identifica un operador con el que puede obtenerse el tipo de objetos y
expresiones en tiempo de ejecución. Permite comprobar si un objeto es de un tipo
particular, y si dos objetos son del mismo tipo.

Sobrecarga de Operadores Binarios.


Un operador binario tiene dos operandos o argumentos, uno a cada lado del operador.
El operador “/”, por ejemplo, es binario. Algunos operadores tales como “+” son unitarios y
binarios, dependiendo de su uso.
Los operadores binarios pueden ser sobrecargados de dos formas:
a. Declarando una función miembro no estática que acepte un argumento
b. Declarando una función no miembro (generalmente friend) que acepte dos argumentos.

Según lo anterior, y dependiendo de la declaración, si @ representa el operador binario, la


expresión x @ y entre miembros de una clase C puede ser interpretada como cualquiera de
las dos formas:
a. x.operator @ (y)
b. operator @ (x, y)

Nota: recuerde la versión a parece recibir solo un argumento, pero en realidad recibe dos si se
considera el argumento implícito this, de forma que podría considerarse:
x.operator @ (C * this, y) siendo: C * this = &x

En otras palabras, un operador binario se puede sobrecargar pasando a la función dos


argumentos si no es función miembro. El primer argumento es el operando izquierdo del
operador sobrecargado y el segundo argumento es el operando derecho, si la función no es
miembro de la clase.

Consideremos un tipo de clase T y dos objetos x1 y x2 de tipo T


Definamos un operador binario “+” sobrecargado, entonces:
x1 + x2 se interpreta como: operator + (x1, x2)
Programación II. Guía 7 5
Un operador binario puede, por consiguiente, ser definido así:
• Como una función de dos argumentos
• Como una función miembro de un argumento (el caso más frecuente)
• Nunca las dos a la vez.

Sobrecarga de los operadores de manejo de flujos de entrada “>>” y de flujos de salida


“<<” Binarios.
Un caso especial es la sobrecarga de los operadores “<<” y “>>” utilizados en la salida u
entrada de datos respectivamente. Estos operadores se encuentran definidos en la biblioteca
iostream de C++.
En el caso de la entrada de datos del teclado a la aplicación, se establece una relación entre
una referencia a un objeto de la clase istream y una referencia a un objeto de la clase en la
cual se está incluyendo la sobrecarga.
La sintaxis es la siguiente:
friend istream & operator >> (istream &, <Nombre de clase> &);

En el caso de la salida de datos de la aplicación a la pantalla, se establece una relación entre


una referencia a un objeto de la clase ostream y una referencia a un objeto de la clase en la
cual se está incluyendo la sobrecarga.
La sintaxis es la siguiente:
friend ostream & operator << (ostream &, <Nombre de clase> &);

Observe que las funciones que se obtienen al sobrecargar los operadores se declaran como
amigas (friend) de la clase en la cual se insertaron. Esto es para que dichas funciones,
externas a la clase, puedan tener acceso a los miembros privados de la misma.

Procedimiento

Ejemplo 1:
En C++, el operador “+” no puede utilizarse para concatenar cadenas.
Sin embargo, si utilizamos una clase propia llamada Cadena, podríamos sobrecargar el
operador “+” para realizar la concatenación de cadenas, como se muestra en el siguiente
ejemplo:
6 Programación II, Guía 7

#include <iostream>
#include <string.h> // Para las funciones de manejo de cadenas: strcpy, strlen y strcat

using namespace std;

class Cadena
{ private:
int longitud; // longitud de la cadena
char *ptrCadena; // Puntero a la cadena de caracteres

public:
Cadena (char [ ]= ""); //constructor predeterminado
Cadena (Cadena &); //constructor por copia
~Cadena(); //destructor
int long_cadena (); //devuelve longitud de la cadena

// Funciones para sobrecarga de operadores


Cadena & operator + (Cadena &); //concatenación

/* Sobrecarga de los operadores de manejo de flujos de entrada ">>" y de flujos de


salida "<<" */
friend ostream & operator << (ostream &, Cadena &);
friend istream & operator >> (istream &, Cadena &);
};

Cadena :: Cadena (char * cadena) //Constructor por defecto


{
longitud = strlen(cadena);
ptrCadena = new char[longitud + 1]; // Creación dinámica

if(ptrCadena == NULL) // Se verifica si hay memoria disponible


{ cout<<"No hay memoria";
exit(0);
}
strcpy(ptrCadena, cadena); // Se copia el contenido de cadena en el objeto creado
}

Cadena :: Cadena (Cadena & copia) //Constructor copia


{
longitud = strlen(copia.ptrCadena);
ptrCadena = new char[longitud + 1];

if(ptrCadena == NULL) // Se verifica si hay memoria disponible


{ cout<<"No hay memoria";
exit(0);
}
strcpy(ptrCadena, copia.ptrCadena); /* Se copia el contenido de copia en el objeto
creado*/
}
Programación II. Guía 7 7

Cadena :: ~Cadena()
{ delete [ ] ptrCadena;
}

// Sobrecarga del operador "+" para que permita concatenar cadenas


Cadena & Cadena :: operator + (Cadena & s)
{
char *temps = ptrCadena;

longitud += s.longitud;
ptrCadena = new char[longitud+1];

if(ptrCadena == NULL) // Se verifica si hay memoria disponible


{ cout<<"No hay memoria";
exit(0);
}

strcpy(ptrCadena, temps); // Se copia el contenido de temps en el objeto creado


strcat(ptrCadena, s.ptrCadena); /* Se realiza la concatenación del contenido de s
con el objeto creado*/
delete [ ] temps; // Se libera memoria reservada con new
return *this;
}

int Cadena :: long_cadena ()


{
return longitud;
}

// Sobrecarga del operador de entrada ">>"


ostream & operator<< (ostream & salida, Cadena & s)
{ salida<< s.ptrCadena;
return salida;
}

// Sobrecarga del operador de salida "<<"


istream & operator>> (istream & entrada, Cadena & s)
{ entrada>> s.ptrCadena;
return entrada;
}

int main()
{ char cad1[20], cad2[20];

system("cls");
cout << "Introducir primer cadena: ";
gets(cad1);
cout << "Introducir segunda cadena: ";
gets(cad2);

Cadena s1(cad1), s2(cad2), s3; //Creamos los objetos de tipo cadena


8 Programación II, Guía 7

//probando operador sobrecargado de concatenación


cout << endl << endl << "Resultado de concatenar Cadenas s1 y s2: " << endl;
s3 = s1 + s2;
cout << "s3: " << s3;

//prueba el constructor de copiado


Cadena *s4= new Cadena(s2);
cout << endl << endl << "Constructor copia para *s4: " << *s4;

//prueba del operador de asignación =


cout << endl << endl << "Asignando s3 a *s4, *s4: ";
*s4 = s3;

cout << *s4 << endl << endl << "Longitud de s4: " << s4 -> long_cadena() << "
caracteres.";

system("pause>nul");
return 0;
}

Ejemplo 2:
En este ejemplo se sobrecargan los operadores aritméticos de la suma y la resta, de tal
manera que puedan operar datos de tipo Vector.

#include <iostream>

using namespace std;

class Vector
{ private:
float CoordX; // Coordenada en eje x del vector
float CoordY; // Coordenada en eje y del vector

public:
Vector (float Va1 = 0, float Val2 =0); //constructor predeterminado
~Vector(){ }; //destructor
void ImprimeVector (); //Muestra el vector

// Funciones para sobrecarga de operadores


Vector operator + (Vector Vec); //Sobrecarga del operador "+" para realizar la
//suma de vectores
Vector operator - (Vector Vec); //Sobrecarga del operador "-" para realizar la
//resta de vectores
};

/* Método constructor con parámetros predeterminados; a los cuales, si no se les


especifican otros valores, se les asignará 0 */
Programación II. Guía 7 9

Vector :: Vector(float Val1, float Val2)


{ CoordX = Val1;
CoordY = Val2;
}

// Método que imprime los valores de los atributos del vector


void Vector :: ImprimeVector( )
{ cout << "La componente en X del vector es: " << CoordX << endl;
cout << "La componente en Y del vector es: " << CoordY << endl;
}

/* Método en el cual se sobrecarga el operador "+"; por lo tanto se podrá utilizar para la
suma aritmética, como para suma de
vectores. Lo anterior da como resultado un objeto de tipo Vector */
Vector Vector :: operator + (Vector Vec)
{ return Vector(CoordX + Vec.CoordX, CoordY + Vec.CoordY);
}

/* Método en el cual se sobrecarga el operador "-"; por lo tanto se podrá utilizar para la
resta aritmética, como para resta de
vectores. Lo anterior da como resultado un objeto de tipo Vector */
Vector Vector :: operator - (Vector Vec)
{ return Vector(CoordX - Vec.CoordX, CoordY - Vec.CoordY);
}

int main()
{
system("cls");
Vector Vec1(3,1), Vec2(1,2), Vec3; //Creamos los objetos de tipo Vector

// Se invoca al operador "+" sobrecargado, es decir, se realiza la suma de vectores


Vec3 = Vec1 + Vec2;

// Mostramos el vector resultante


cout << endl << endl << "Los datos del vector resultante de la suma de vectores son: "
<< endl;
Vec3.ImprimeVector();

// Se invoca al operador "-" sobrecargado, es decir, se realiza la resta de vectores


Vec3 = Vec1 - Vec2;

// Mostramos el vector resultante


cout << endl << endl << "Los datos del vector resultante de la resta de vectores son: "
<< endl;
Vec3.ImprimeVector();

system("pause>nul");
return 0;
}
10 Programación II, Guía 7

Análisis de Resultados

Ejercicio 1:

Modifique el código del ejemplo No. 2, de tal manera que la solución se maneje a través de un
menú que contenga las siguientes opciones:
a) Crear los objetos de tipo vector, solicitando los datos al usuario.
b) Realizar la suma de vectores.
c) Realizar la resta de vectores.
d) Realizar el producto escalar de vectores.
e) Salir de la aplicación.

El programa debe estar debidamente comentado.

Ejercicio 2:

Tomar el código del ejemplo No. 1 como referencia y realizar los cambios que sean necesarios
para crear un programa que provea la funcionalidad necesaria para trabajar con cadenas de
caracteres.
La funcionalidad debe implementarse con un menú con las siguientes opciones:
Opción de menú 1: Ingresar las cadenas de caracteres (como mínimo dos).
Opción de menú 2: Concatenar cadenas.
Opción de menú 3: Comparación de cadenas de caracteres. Considerar la sobrecarga de los
operadores ==, <, >, !=
Opción de menú 4: Determinar si una cadena está vacía. Considerar la sobrecarga del
operador “ ! “
Opción de menú 5: Acceder a un carácter individual en una cadena, es decir, realizar una
Opción de menú 6: Determinar la longitud de una cadena.
Opción de menú 7: Salir del programa.

El menú deberá estar siempre activo, en la misma posición en pantalla, hasta que el usuario
seleccione la opción salir.
El programa debe estar debidamente comentado.

Se sugiere utilizar la declaración de la clase Cadena mostrada a continuación:


Programación II. Guía 7 11
class Cadena
{ private:
int longitud; // longitud de la cadena
char *ptr; // Puntero a la cadena de caracteres

public:
Cadena (char []= ""); //constructor predeterminado
Cadena (Cadena &); //constructor por copia
~Cadena(); //destructor
int long_cadena (void); //devuelve longitud de la cadena

// Funciones para sobrecarga de operadores


bool operator == (Cadena &); //prueba si s1 = s2
bool operator != (Cadena &); //prueba si s1 != s2
bool operator ! ( ); //prueba si Cadena esta vacía
bool operator < (Cadena &); //prueba si s1 < s2
bool operator > (Cadena &); //prueba si s1 > s2
Cadena & operator + (Cadena &); //concatenación
char operator[] (int); //operador de subíndice

/* Sobrecarga de los operadores de manejo de flujos de entrada ">>" y de flujos de salida


"<<" */
friend ostream & operator<< (ostream &, Cadena &);
friend istream & operator>> (istream &, Cadena &);
};
12 Programación II, Guía 7

Guía 7: Sobrecarga de Operadores. Hoja de cotejo: 7

Alumno: Máquina No:

Docente: GL: Fecha:

EVALUACIÓN

% 1-4 5-7 8-10 Nota

CONOCIMIENTO Del 20 Conocimiento Conocimiento Conocimiento


al 30% deficiente de y explicación completo y
los fundamentos incompleta de explicación
teóricos los clara de los
fundamentos fundamentos
teóricos teóricos
APLICACIÓN Del 40%
DEL al 60%
CONOCIMIENTO

ACTITUD
Del 15% No tiene Actitud Tiene actitud
al 30% actitud propositiva y proactiva y
proactiva. con sus
propuestas no propuestas
aplicables al son
contenido de concretas.
la guía.
TOTAL 100%