Logo Studenta

Slides TD Parcial2-41-50

¡Estudia con miles de materiales!

Vista previa del material en texto

Ejemplo: Tipo Complejo
Vamos a definir un tipo abstracto Complejo para describir números
en el plano complejo representados de manera cartesiana (a+ bi
donde a y b son respectivamente las magnitudes real e imaginaria) y
de manera polar (re iα) donde α es un ángulo y r es el módulo.
α
a
b
r
a+ bi = reαi
7
Complejo en C++ : parte pública
1 class Complejo {
2 public:
3 // observadores
4 float re() const; // parte real
5 float im() const; // parte imaginaria
6
7 // constructores
8 Complejo(float real, float imag);
9 static Complejo crear_polar(float mod, float ang);
10
11 // modificadores
12 void conjugar();
13
14 // otras operaciones:
15 Complejo operator+(const Complejo & b) const;
16 float modulo() const;
17 float angulo() const;
18 /* ... sigue ... */
9
Tipo abstracto – Especificación de operaciones
Usaremos la sintaxis de contratos vista en la primera parte, con las
siguientes modificaciones:
I Los métodos de la clase T tienen un parámetro implícito
T* this, que apunta al objeto sobre el cual se está operando.
Un método const no permite modificar this.
I Especificaremos Pre y Post de las operaciones en función de los
observadores aplicados a this y/o a objetos del tipo
especificado que se pasen como parámetro.
I Observadores: conjunto minimal de métodos const que
devuelven la información que caracteriza la instancia. Pueden
tener Pre sobre los parámetros de entrada pero no tienen Post.
I Constructores: la Pre sólo predica sobre los parámetros de
entrada; la Post sobre el estado final del objeto en base a los
observadores
I Modificadores: modifican la instancia, potencialmente
devolviendo además un resultado. En la Post se especifica cómo
cambia la salida de los observadores, usando this y this0.
10
Ejemplo: Tipo Complejo – Espec. de operaciones
Tipo Complejo
Observadores:
I float re() const // parte real
I float im() const // parte imaginaria
Constructores:
I Complejo(float real,float imag)
Post: *this.re() = real ∧ *this.im() = imag
I static Complejo crear_polar(float mod, float ang)
Post: res.re() = mod*cos(ang) ∧ res.im() = mod*sin(ang)
Los métodos static son “de clase” y se ejecutan sin un objeto this sobre el
cual operar. En este ejemplo, crear_polar sigue el patrón de constructor con
nombre: una función que oficia de constructor.
11
Modificadores:
I void conjugar()
Pre: this = this0
Post: *this.re() = *this0.re()∧
*this.im() = −(*this0.im())
Otras operaciones:
I Complejo operator+(const Complejo & b) const
Post: res.re() = *this.re()+ b.re() ∧
res.im() = *this.im()+ b.im()
I float modulo() const
Post: res =
√
*this.re()2 + *this.im()2
I float angulo() const
Post: res = arctan2(*this.im(), *this.re())
12
Ejemplo: Tipo Conjunto<T>
Objetivo: abstraer el comportamiento de un
conjunto de elementos de tipo T.
Consideraciones:
I La operación que caracteriza a un conjunto es el ∈ (pertence).
I Es decir, un conjunto C queda definido completamente por qué
elementos contiene o no.
I Otras operaciones que tiene sentido modelar: ∪ (unión) y ∩
(intersección).
I También es necesario poder agregar/quitar de a un elemento al
conjunto.
13
Ejemplo: Tipo Conjunto<T> – Interfaz
Observadores:
I bool pertenece(const T & elem) const
Constructores:
I Conjunto<T>()
Post: (∀t : T ) *this.pertenece(t) = false
Modificadores:
I void agregar(const T& e)
Pre: this = this0
Post: (∀e′ : T ) *this.pertenece(e′) = true
⇐⇒ (*this0.pertenece(e′) = true ∨ e′ = e)
I void quitar(const T& e)
Pre: this = this0
Post: (∀e′ : T ) *this.pertenece(e′) = true
⇐⇒ (*this0.pertenece(e′) = true ∧ e′ 6= e)
14
Más modificadores:
I void unir_con(const Conjunto<T> & c)
Pre: this = this0
Post: (∀e : T ) *this.pertenece(e) = true
⇐⇒ (*this0.pertenece(e) = true
∨ c.pertenece(e) = true)
I void intersecar_con(const Conjunto<T> & c)
Pre: this = this0
Post: (∀e : T ) *this.pertenece(e) = true
⇐⇒ (*this0.pertenece(e) = true
∧ c.pertenece(e) = true)
Otras operaciones:
I int cardinal() const
Post: res =
∑
e∈T β(*this.pertenece(e) = true)
Nota: Esta sumatoria es sobre un dominio infinito
15
Conjunto<T> en C++: interfaz
1 template <typename T>
2 class Conjunto {
3 /*...*/
4 }
La palabra clave template
I Si queremos implementar clases como vector<T> que tiene un
parámetro de tipo T, necesitamos, en C++, usar templates para
poder dejar a T a elección del usuario.
I Un template define una “receta” para crear clases y funciones.
Por ejemplo, vector es un template, y vector<int>,
vector<float> y vector<vector<bool>> son tres posibles
clases concretas que se fabrican a partir de ese template.
I Instanciar un template es análogo a hacer copy-paste del
template reemplazando T por el tipo elegido.
16
Conjunto<T> en C++: interfaz
1 template <typename T>
2 class Conjunto {
3 public:
4 // observadores
5 bool pertenece(const T& elem) const;
6
7 // modificadores
8 void unir_con(const Conjunto& c);
9 void intersecar_con(const Conjunto& c);
10 void agregar(const T& elem);
11 void quitar(const T& elem);
12
13 // otras operaciones
14 int cardinal() const;
15 /** ... sigue ... **/
17

Continuar navegando