Practica2

=Practica 2: Operadores=

En la lección anterior indicamos que los operadores nos permitían utilizar operadores típicos como +,-,*,/,++. En esta lección vamos a estudiar a fondo su uso. Partiremos de la clase Float, que hicimos en el tema anterior.

**1. Operadores aritméticos**
Los operadores aritméticos no modifican el objeto actual. Lo que hacen es que devuelven uno que es el resultado de la operación a realizar. Veamos un ejemplo. En float.h

code format="cpp" /**Addition operator Float operator+(const Float &  F); code En float.cpp code format="cpp" Float Float::operator+(const Float & F) { Float aux; aux._fvalue=_fvalue+F._fvalue; return aux; }

code Podeis probar el codigo como code format="cpp" int main(int argc,char **argv) { Float F(10); Float F2(19); Float F3; F3=F+F2; cout<< F3.getValue<<endl; } code

Como se puede observar, esta función retorna un objeto de la clase Float. Este objeto es retornado para poder realizar encadenamiento de operadores, ej: code format="cpp" F3+F2+10; code De forma alternativa, podríamos haber implementado el código como: code format="cpp" Float Float::operator+(const Float & F) { return Float(_fvalue+F._fvalue); }

code

A este tipo de declaración se le denomina implícita. Como se puede ver, se esta creando un objeto de tipo Float (invocando al constructor), pero no se esta usando ninguna variable para guardarlo. Esto se suele hacer para estos casos en que no se va a hacer uso de la variable. Sin embargo, el código anterior equivalente a: code format="cpp" Float Float::operator+(const Float & F) { Float aux(_fvalue+F._fvalue) return aux; } code

La única diferencia es que estamos escribiendo menos código.

1.1 Ejercicio
Implemente más operadores para la clase Float. En este caso, solo se indicará la declaración que deberá estar en el .h y usted tendrá que crear la implementación en el .cpp

code format="cpp" /** Addition operator Float operator+(float f); /** Substraction operator Float operator-(const Float & F);

/** Substraction operator Float operator-(float f);

/** Multiplication operator Float operator*(const Float & F);

/** Multiplication operator Float operator*(float f);

/** Division operator Float operator/(const Float & F);

/** Division operator Float operator/(float f);

code

2. Operadores de comparación
Los operadores de comparación son extremadamente útiles y también pueden ser sobrecargados. Veamos un ejemplo con el operador <.

En el float.h code format="cpp" /** less operator bool operator<(const Float & F);

code En el float.cpp code format="cpp" bool Float::operator<(const Float & F) { return _fvalue < F._fvalue; }

code

Aquí nos encontramos algo nuevo, el tipo de datos bool. Este tipo de datos es nuevo de C++ y sirve para identificar una variable booleana. Por tanto, solo puede tener dos valores true o false. Veamos un pequeño ejemplo:

code format="cpp" int main { bool myBolean=false; if ( myBolean) cout<<"Is false"<(const Float & F);

/**greater-equal operator bool operator>=(const Float & F);

/**equal operator bool operator==(const Float & F);

/**not equal operator bool operator!=(const Float & F); code

b) Ahora implemente de nuevo estos operadores pero recibiendo como parámetro un flotante (float) en lugar de un objeto de la clase Float.

3. Operadores Unarios
Los operadores unarios son de gran utilidad en la programación en C++. También es posible implementarlos. En float.h code format="cpp" /**Increment operator Float & operator++(int);

/**Decrement operator Float & operator--(int);

code

El caso es que estos operadores reciben como argumento un entero, que no se suele usar.

En .cpp

code format="cpp" //////////////////////////// // //////////////////////////// Float & Float::operator++(int) { _fvalue++; return *this; }

//////////////////////////// // //////////////////////////// Float & Float::operator--(int) { _fvalue--; return *this; }

code

4. Corrección del trabajo
En esta sección vamos a comprobar que los ejercicios se han realizado correctamente. Para ello, deberemos usar el siguiente programa de prueba. Usted deberá copiar el siguiente código en el fichero pruebafloat.cpp y modificar el makefile para que permita compilarlo.

Fichero pruebafloat.cpp

code format="cpp" using namespace std; using namespace values; int main(int argc,char **argv) { Float F(10); Float F2=F; assert(F2==F); Float F3=F=10; //La funcion assert, comprueba que la evaluacion sea true. //En caso de que sea false, para el programa en y nos lo indica assert(F3==10); assert(F3==F); assert(!(F3>F)); F3=10; F=1; assert(F3>=F); assert(F3!=F); F2=1; F=F2*10; assert(F==10); F=F2/10.; assert(F==0.1); F2=10; F=F2+10+10; assert(F==30); assert(F>10); assert(F>=30); assert(F<=30); assert(F<50); assert(F!=20); F++; F--; assert(F==30); cout<<"Perfect"<
 * 2) include
 * 3) include

El programa realiza una prueba de todos los elementos que hemos creado.

1.4.1 Algo más sobre el makefile
En el makefile es posible tener varios objetivos de compilación y seleccionar cuál de ellos usar. Veamos un ejemplo de makefile:

code all:float float:float.cpp main.cpp g++ -I. float.cpp main.cpp -o float prueba: float.cpp pruebafloat.cpp g++ -I. pruebafloat.cpp float.cpp -o pruebafloat clean: rm pruebafloat float *~ -f

code

En el makefile anterior, tenemos cuatro reglas de ejecucón: all, float, prueba y clean. La regla all es la regla por defecto. De tal forma que cuando hacemos make en la consola, se ejecuta la regla all. En este fichero, la regla all depende de que se cumpla la regla float, por tanto, el programa makefile se va a ejecutar la regla float. La regla float depende de los ficheros float.cpp y main.cpp. De esta forma, si alguno de los dos ficheros cambia, se ejecuta la regla de compilación. Por otro lado, tenemos la regla prueba. Para que se ejecute, tendremos que hacer en consola un make prueba. Finalmente, tenemos la regla clean que limpia el directorio. Para que se cumpla hay que indicar en consola //make clean//.

1.4.2 Opción de depuración
Podemos indicar al compilador que nos cree el programa con la maxima información de depuración posible con la opción -g3.

code g++ -I. -g3 float.cpp main.cpp -o float code De esta forma, podemos usar programas como el kdbg o ddd para depurar el ejecutable.

5. Ejercicios
Implemente la clase Double (dentro del espacio de nombres values), con todas las funciones miembro indicadas (todos los operadores de la practica 1 y de esta).

6. Para avanzados
Hasta ahora nohemos definido operadores para que trabajen por la derecha con otros elementos. Sin embargo, algo como code format="cpp" F=10/F2; code no sería posible ya que no hemos definido esta función. C++ nos permite hacer esto de la siguiente forma. En float.h

code format="cpp" friend Float operator/(float f,const Float & F); code y en el float.cpp code format="cpp" Float operator/(float f,const Float & F) { return Float(f/F._fvalue); } code Hemos definido lo que se llama una función amiga que recibe como primer parámetro un float y como segundo un Float. Esto se puede hacer para todos los operadores.

Alternativamente, podríamos haber definidos los operadores code format="cpp" Float operator/(const Float &F); code de forma amiga como

code format="cpp" friend Float operator/(const Float &F,const Float F2); code