Introducción

Download Report

Transcript Introducción

Introducción a clases
Programación Orientada a
Objetos
Clases
Una clase es un tipo de datos que incluye datos llamados
miembros y funciones llamados métodos.
La clase es una plantilla a partir de la cual se pueden definir
variables conocidas como objetos.
Los objetos son instancias o ejemplares de alguna clase.
Las clases en C++ se pueden declarar como estructuras
(struct) o como clases (class), en el primer caso sus
miembros serán por omisión públicos y en el segundo serán
privados.
Motivación
Considere el concepto de fecha definido como una estructura y
las funciones que manipulan esta estructura:
struct Fecha{
int d, m, a;
};
void inicia_fecha(Fecha& d,int dd, int mm, int aa){
d.d = dd; d.m = mm; d.a = aa;
}
void suma_anyo(Fecha& d,int n){
d.a += n;
}
void suma_mes(Fecha& d,int n){
d.m += n;
}
void suma_dia(Fecha& d,int n){
d.d += n;
}
void imprime(Fecha d){
cout << d.d << "/" << d.m << "/" << d.a << endl;
}
Es posible escribir una función main como la siguiente que
manìpule una variable de tipo Fecha sin usar las funciones definidas
anteriormente.
main(){
Fecha hoy;
inicia_fecha(hoy,14,2,2013);
suma_anyo(hoy,1);
imprime(hoy);
hoy.d += 5;
hoy.a = hoy.d*hoy.m;
imprime(hoy);
system("pause");
}
La clase Fecha
Declaramos las funciones como miembros de la estructura
para ligarlas con los datos de una fecha.
Miembros dato
struct Fecha{
int d, m, a;
void inicia_fecha(int dd, int mm, int aa);
void suma_anyo(int n);
void suma_mes(int n);
void suma_dia(int n);
void imprime();
};
Métodos
La declaración de las funciones debe especificar el nombre de la
estructura a la que pertenecen.
void Fecha::inicia_fecha(int dd, int mm, int aa){
d = dd; m = mm; a = aa;
}
void Fecha::suma_anyo(int n){
a += n;
}
void Fecha::suma_mes(int n){
m += n;
}
void Fecha::suma_dia(int n){
d += n;
}
void Fecha::imprime(){
cout << d << "/" << m << "/" << a << endl;
}
Con estas declaraciones todavía es posible ejecutar la función
main vista anteriormente con algunas modificaciones.
Para invocar los métodos se utiliza el operador “.”. La
invocación se conoce como envío de un mensaje.
Envío de mensajes al objeto
hoy.
main(){
Fecha hoy;
hoy.inicia_fecha(14,2,2013);
hoy.suma_anyo(1);
hoy.imprime();
hoy.d += 5;
hoy.a = hoy.d*hoy.m;
hoy.imprime();
system("pause");
}
Para restringir la manipulación de variables de tipo Fecha solo a
través de las funciones definidas, debemos declarar (definir) una
clase (class) en lugar de una estructura (struct).
Cualquier intento de referenciar los campos d, m, a de la clase
generará un mensaje de error.
class Fecha{
int d, m, a;
Modificador de acceso
public:
void inicia_fecha(int dd, int mm, int aa);
void suma_anyo(int n);
void suma_mes(int n);
void suma_dia(int n);
void imprime();
};
Métodos poner y obtener
Dado que los miembros dato son privados, es necesario definir
métodos públicos para obtener o poner el valor de estos.
La clase Fecha con métodos para poner y obtener los miembros
dato es la siguiente.
class Fecha{
int d, m, a;
public:
void inicia_fecha(int dd,
int mm, int aa);
void suma_anyo(int n);
void suma_mes(int n);
void suma_dia(int n);
void imprime();
int obtieneDia();
int obtieneMes();
int obtieneAnyo();
void ponDia(int n);
void ponMes(int n);
void ponAnyo(int n);
};
La clase Grados
Construyamos una clase para manipular cantidades en grados,
minutos y segundos. Supondremos solo valores enteros para estas
cantidades.
La siguiente es una primera declaración de la clase.
class Grados{
int grad, min, seg;
public:
void poner(int g, int m, int s);
void sumar(Grados a);
void escribe();
};
void Grados::poner(int g, int m, int s){
//este método pone valores a los miembros del
objeto
grad = g; min = m; seg = s;
}
void Grados::sumar(Grados a){
//este método suma al objeto otro objeto
seg += a.seg;
if(seg>=60){
min += seg/60;
seg = seg%60;
}
min += a.min;
if(min>=60){
grad += min/60;
min = min%60;
}
grad += a.grad;
}
void Grados::escribe(){
//este método despliega los valores de grados,
minutos y segundos
cout << grad << "g" << min << "'" << seg << "\"\n";
}
La siguiente función main crea dos objetos de clase Grados y
suma el segundo al primero.
main(){
Grados a,b;
a.poner(30,45,35);
b.poner(3,18,34);
a.escribe();
b.escribe();
a.sumar(b);
a.escribe();
system("pause");
}
30º45’35”
3º18’34”
Despliega:
34g4’9”
Los métodos que consten de pocas líneas es conveniente que se
escriban como funciones en línea en la declaración de la clase,
como se muestra:
class Grados{
int grad, min, seg;
public:
void poner(int g, int m, int s)
{grad=g;min=m;seg=s;};
void sumar(Grados a);
void escribe(){
cout<<grad<<"g"<<min<<"'"<<seg<<“\"\n“;
};
Constructores
Un constructor es un método que se ejecuta al crear variables
de alguna clase.
La definición de constructores permite controlar desde un inicio
los valores almacenados en los objetos.
Los constructores pueden ser funciones sobrecargadas, es decir,
puede haber varios constructores para una clase.
Los constructores en C++ son métodos que tiene el mismo
nombre que la clase y no llevan ningún tipo de retorno.
La siguiente versión de la clase Grados tiene dos constructores,
uno sin parámetros y otro con tres parámetros.
class Grados{
int grad, min, seg;
public:
Grados(){grad=0;min=0;seg=0;};
Grados(int g, int m, int s){grad=g;min=m;seg=s;};
void poner(int g, int m, int s){grad=g; min=m;
seg=s;};
void sumar(Grados a);
void escribe(){cout<<grad<<"g"<<min<<"'“<<seg<<
"\"\n";};
};
La siguiente función main crea dos objetos. El objeto a se crea
con el constructor con parámetros y b con el constructor sin
parámetros.
main(){
Grados a(30,45,35),b;
b.poner(3,18,34);
a.escribe();
b.escribe();
a.sumar(b);
a.escribe();
system("pause");
}
Listas de inicialización
Otra forma de especificar los constructores es mediante una lista de
inicialización.
La lista de inicialización consta de una lista de los miembros de la
clase con valores encerrados entre paréntesis, como se muestra.
class Grados{
Lista de inicialización
int grad, min, seg;
public:
Grados():grad(0),min(0),seg(0){};
Grados(int g, int m, int s):grad(g),min(m),seg(s){};
void poner(int g,int m,int s){grad=g;min=m;seg=s;};
void sumar(Grados a);
void
escribe(){cout<<grad<<"g"<<min<<"'"<<seg<<"\"\n";};
};
Constructor de copia
Un constructor de copia acepta como parámetro un objeto de la
clase y lo copia en el objeto actual.
Estos constructores sólo tienen un argumento, que es una
referencia a un objeto de su misma clase.
En general, los constructores copia tienen la siguiente forma para
sus prototipos:
tipo_clase::tipo_clase(const tipo_clase
&obj);
Si no se define un constructor de copia el compilador crea un
constructor de copia oficial.
El constructor de copia puede llevar más parámetros además de
la referencia a un objeto de su misma clase.
Constructor de copia de Grados
Constructor
class Grados{
de copia
int grad, min, seg;
public:
Grados():grad(0),min(0),seg(0){};
Grados(const Grados& a):grad(a.grad),min(a.min),
seg(a.seg) {};
Grados(int g, int m, int s):grad(g),min(m),seg(s){};
void poner(int g, int m, int s){grad=g;min=m;seg=s;};
void sumar(Grados a);
void escribe(){cout<<grad<<"g"<<min<<"'"<<seg<<
"\"\n";};
};
La siguiente función main muestra el uso del constructor de
copia. Note que la instrucción c = b, llama al constructor de
copia.
main(){
Grados a(30,45,35),b(a),c = b;
a.escribe();
b.escribe();
c.escribe();
Constructor de copia
a.sumar(b);
a.escribe();
system("pause");
}
Destructores
Un destructor es un método que se invoca cuando un objeto deja
de existir, por ejemplo al salir de una función con un objeto local.
Los destructores tienen el mismo nombre que los constructores
pero se les antepone el símbolo ~.
Los destructores no llevan parámetros ni regresan ningún valor.
Los destructores se utilizan para eliminar datos credos por el
objeto tales como variables dinámicas.
Ejemplo de destructor
La siguiente versión de la clase Grados incluye un destructor.
El destructor solo despliega un mensaje en la pantalla.
class Grados{
int grad, min, seg;
public:
Grados():grad(0),min(0),seg(0){};
Grados(int g, int m, int s):grad(g),min(m),seg(s){};
~Grados(){cout << "Destructor invocado.\n";};
void poner(int g, int m, int s){grad=g;min=m;seg=s;};
void sumar(Grados a);
void
escribe(){cout<<grad<<"g"<<min<<"'"<<seg<<"\"\n";};
};
La siguiente función prueba la ejecución del destructor.
void pruebaDestructor(){
Grados a;
a.escribe();
}
main(){
Grados a(30,45,35),b;
b.poner(3,18,34);
a.escribe();
b.escribe();
a.sumar(b);
a.escribe();
pruebaDestructor();
system("pause");
}
¿Por qué aparece dos veces el
letrero “Destructor invocado.” ?
Asignación dinámica de memoria
Es común la creación de objetos de forma dinámica.
Para crear usamos el operador new y para destruir el operador
delete. No es necesario utilizar las bibliotecas estándar para este
propósito.
main(){
Fecha *hoy;
hoy = new Fecha;
hoy->inicia_fecha(14,2,2013);
hoy->imprime();
hoy->suma_anyo(1);
hoy->imprime();
delete hoy;
system("pause");
}
El apuntados this
El apuntador this representa un apuntador a un objeto cuya
función miembro esta siendo ejecutada.
Es una apuntador al objeto en si.
Ejemplo de this
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme(CDummy& param);
};
int CDummy::isitme(CDummy& param){
if(&param == this)
return true;
else
return false;
}
main(){
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) )
cout << "yes, &a is b";
system("pause");
return 0;
}
Miembros estáticos
Se pueden declarar datos o métodos estáticos.
Un miembro dato estático solo almacena un valor para todos
los objetos de la clase.
Se comporta como una variable global, pero con acceso
restringido.
Se utiliza por ejemplo, para llevar una cuenta del número de
objetos declarados de alguna clase.
Las variables static pueden existir aun sin la declaración de
ningún objeto de la clase.
Ejemplo de miembro static
#include <iostream>
using namespace std;
class CDummy {
public:
static int n;
CDummy () { n++; };
~CDummy () { n--; };
};
int CDummy::n=0;
int main () {
CDummy a;
CDummy b[5];
CDummy * c = new CDummy;
cout << a.n << endl;
delete c;
cout << CDummy::n << endl;
system("pause");
return 0;
}
Clase Racional
La siguiente clase permite definir operaciones con números
racionales.
Un número racional consta de dos componentes enteras, el
numerador y el denominador.
La clase implementa las operaciones de suma, resta,
multiplicación, división y simplificación de racionales. Además
definimos 3 constructores y un método para desplegar racionales.
Separaremos la clase racional en dos archivos. Un archivo de
encabezado (.h) y un archivo de implementación (.cpp).
Racional.h
class Racional{
int num,den;
public:
Racional(){num = 0;den = 1;};
Racional(int a){num = a;den = 1;};
Racional(int a,int b){num=a;den=b;simplifica();};
void suma(Racional a);
void resta(Racional a);
void miltiplica(Racional a);
void divide(Racional a);
void simplifica();
void escribe();
};
Racional.cpp
/*Clase Racional: Implementación*/
#include <iostream>
#include "racional.h"
using namespace std;
void Racional::suma(Racional a){
num = num*a.den+den*a.num;
den = den*a.den;
simplifica();
}
void Racional::resta(Racional a){
num = num*a.den-den*a.num;
den = den*a.den;
simplifica();
}
Racional.cpp (cont.)
void Racional::miltiplica(Racional a){
num = num*a.num;
den = den*a.den;
simplifica();
}
void Racional::divide(Racional a){
num = num*a.den;
den = den*a.num;
simplifica();
}
void Racional::escribe(){
cout << num << "/" << den << "\n";
}
Racional.cpp (cont.)
void Racional::simplifica(){
int a,b,res;
if(num>den){
a = num;
b = den;
} else{
a = den;
b = num;
}
while(b != 0){
res = a%b;
a = b;
b = res;
}
num = num/a;
den = den/a;
}
Archivo main
#include <cstdlib>
#include <iostream>
#include "racional.h"
using namespace std;
main(){
Racional r(5),s(12,36);
r.escribe();
s.escribe();
r.suma(s);
r.escribe();
system("pause");
}