ClasesdeObjetos
Tema2:Clasesdeobjetos1.Implementacindeunaclase1.DescripcindeunaclaseenC++ 2.Elementospblicosyprivados 3.Accesoaatributos 4.Clasesamigas 5.Implementacindelasoperaciones 6.Funcionesmiembroinline 7.OrganizacindelcdigoenC++
2.Inicializacinyfinalizacindeclases1.Constructores 2.Destructores
1
ClasesdeObjetos
ImplementacindelasclasesPartiendodeldiseoorientadoaobjetosdeun sistema,latareabsicaalaquenosenfrentamos durantelafasedeimplementacineslatraduccinde cadaclaseallenguajedeprogramacinorientadoa objetosqueestemosutilizandoCuenta nmero:string titular:string saldo:float intersAnual:float ingreso(cantidad:float) reintegro(cantidad:float) ingresoInteres() estaEnRojos():bool verSaldo():float
Ejemplo:unobjetoquerepresentalas cuentasenunaaplicacindegestin bancaria.
2
ClasesdeObjetos
DescripcindeunaclaseenC++Ficherocuenta.hclass Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos(); float verSaldo(); };
Atributos(variablesmiembro)
Cuenta nmero:string titular:string saldo:float inters:float +ingreso(cantidad:float) +reintegro(cantidad:float) +ingresoInteres() +estaEnRojos():bool +verSaldo():float
Operaciones(funcionesmiembro)
3
ClasesdeObjetos
ElementospblicosyprivadosSeccinpublic(pblica):miembrosaccesiblesdesde elexteriordelaclase.Smbolo+enUML Seccinprivate(privada):protegeloselementoscuyo accesodesdeelexteriornoestpermitido.Por defectotodossonprivados.SmboloenUMLclass Cuenta { private: char numero[20]; char titular[80]; float saldo; float interes; public: void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos(); float verSaldo(); };
Seccinprivada (privatees opcional)
Seccinpblica4
ClasesdeObjetos
Lasutilidaddelasoperacionesprivadasesservir comoauxiliaresaotrasoperacionesdelaclaseFuncinmiembroprivada auxiliar(usadapor ingresoyreintegro)class Cuenta { char numero[20]; char titular[80]; float saldo; float interes; void modificarSaldo(float cantidad); public: void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos(); float verSaldo(); };
5
ClasesdeObjetos
Accesoaatributos.AtributospblicosEnmuchasocasionesesnecesarioqueelvalorde unatributoseavisibledesdeelexteriorparalectura Establecercomounatributocomopblicoesposible, peropocorecomendableElatributopuedesermodificadodesdeelexteriorsinningncontrol Seestableceunadependenciaentrelarepresentacininternadelaclaseyel exteriorclass Cuenta { char numero[20]; char titular[80]; float interes; public: float saldo; void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos(); };6
Elatributosaldopuede situarseenlapartepblica paraquepuedaser consultadodesdeelexterior (pocorecomendable)
ClasesdeObjetos
Esmuchomsseguroutilizaroperacionespara controlarelaccesoaestosatributos,aunquepueda suponerunamnimapenalizacineneltiempode accesoclass Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: void ingreso(float cantidad); void reintegro(float cantidad); float verSaldo(); void ingresoInteres(); int estaEnRojos(); };
Estasfuncionespermiten tantolamodificacincomola lecturadelatributosin permitirunaccesodirecto
7
ClasesdeObjetos
ClasesamigasAvecesdosclasesestntanntimamente relacionadasqueunarequiereaccesototalavarios atributosyoperacionesprivadosdelaotra. Esteaccesopuedegarantizarsepermitiendoel accesoabsolutodeformaselectivasloa determinadasclases,denominadasamigasLaclaseInformeCuentarealizauninformeimpresodelestadode unaCuentacontodossusdatos.Paraellonecesitaaccederatodoslos atributosdelaclase,perostossonprivadosynoexistenentodosloscasos operacionesparaobtenersuvalor
8
ClasesdeObjetos
Solucin:hacerlaclaseInformeCuentaamigadeCuentaparaquetenga accesocompletoasusatributos
InformeCuenta ttulo:string fecha:Fecha imprimir(c:Cuenta)
Hacerunaclaseamigadeotraespermitir selectivamentelaviolacindelasreglasdeocultacin deinformacin Ladeclaracindeclasesamigasdeberealizarsecon moderacinysloencasosenqueestplenamente justificado9
ClasesdeObjetos
ApartirdeahoralaclaseInformeCuentaesamigadeCuentaytiene accesocompletoasusatributosprivadosyobviamentepblicos
class Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: friend class InformeCuenta; void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos(); float verSaldo(); };
10
ClasesdeObjetos
ImplementacindelasoperacionesDependiendodellenguajedeprogramacin,la implementacindelasoperacionesserealizaenel mismositioquelainterfazdelaclase(Java,Eiffel)o enficherosseparados,comoenC++:Ficherocuenta.cppvoid Cuenta::ingreso(float cantidad) { saldo += cantidad; } void Cuenta::reintegro(float cantidad) { saldo -= cantidad; }
Calificadordeclase.Indicala clasealaquepertenecela funcinmiembro implementada
11
ClasesdeObjetos
Desdecadaoperacin,elaccesoaunatributodela claseesdirecto,comosisetrataradeunavariable localdefinidaencadaunadelasoperacionesTambinesposibleelusodelcalificador: ::saldoIndicacindequesetratadeunavariableexterna(nopertenecientea ningunaclase). Cuenta::saldo Especificalaclasealaqueperteneceelatributo.Sirvepara resolversituacionesdeambigedad.void Cuenta::ingresoInteres() { saldo += saldo * interes / 100; } int Cuenta::estaEnRojos() { return saldo < 0; } float Cuenta::verSaldo() { return saldo; }
12
ClasesdeObjetos
Funcionesinline(enlnea)Unallamadaaunafuncinmiembroinlinegeneraun cdigomuyeficienteyaquenogenerarealmenteuna llamadaninecesitacdigodepreparacindestaGeneracindecdigoenuna llamadaafuncinordinaria... MOV B, A CALL ver_saldo SUM B, 30H ...
Generacindecdigoenuna llamadaafuncininline... MOV B, A MOV AX, saldo SUM B, 30H ...
Cuenta::verSaldo()MOV AX, saldo PUSH AX RETURN13
ClasesdeObjetos
Lasfuncionesinlineseimplementandirectamenteen lainterfazdelaclase Lasfuncionesqueseimplementantpicamentecomo inlinesonpequeasysimples(lecturadevaloresde atributos,comprobacionessencillas,etc.)class Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos() { return saldo < 0; } float verSaldo() { return saldo; } };
14
ClasesdeObjetos
OrganizacindelcdigoenC++Lainterfazdelaclaseseincluyeenunficherodecabecera// -----------------------------------------// cuenta.h - Interfaz de la clase Cuenta // -----------------------------------------#ifndef CUENTA_H #define CUENTA_H class Cuenta { char numero[20]; char titular[80]; float saldo; float interes;
// Variables miembro
public: // Funciones miembro void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos() { return saldo < 0; } float verSaldo() { return saldo; } }; #endif15
ClasesdeObjetos
Laimplementacindelasfuncionesmiembroquenoseaninline,serealizaen unficherofuenteconelmismonombrequeelficherodecabecera correspondiente// -------------------------------------------------// Cuenta.cpp - Implementacin de la clase Cuenta // -------------------------------------------------#include "cuenta.h" void Cuenta::ingreso(float cantidad) { saldo += cantidad; } void Cuenta::reintegro(float cantidad) { saldo -= cantidad; } void Cuenta::ingresoInteres() { saldo += saldo * interes / 100; } // Fin de Cuenta.cpp -------------------------------16
ClasesdeObjetos
InicializacindeunaclaseYasabemoscomodefiniratributosenunaclase, peroquevalorinicialtienenestosatributoscuando enelmomentodelacreacindeunobjetodedicha clase? Esnecesariopoderinicializarunobjetoantesde comenzaratrabajarconl.Lastareastpicasenla inicializacinson:Inicializacindeatributos Asignacindememoriadinmica Aperturadearchivos
17
ClasesdeObjetos
Unaprimerasolucinconsisteendefiniruna operacindeinicializacindelaclasevoid Cuenta::inicializar(char *anumero, char *atitular, float asaldo, float ainteres) { strcpy(numero, anumero); strcpy(titular, atitular); saldo = asaldo; interes = ainteres; }
Estanoesunasolucinfiable:Obligaalusuarioaconocercualeslafuncinmiembrodeinicializacindelobjeto, quepuedetenermuchosnombres:inicializa,inicializar,nueva,crear,etc. Sielusuarioolvidallamaralafuncinmiembrodeinicializacintras crearelobjetosurgirnmuchosproblemas...
18
ClasesdeObjetos
Laprogramacinorientadaaobjetosproporcionaun mediomuchomsseguro:losconstructores Unconstructoresunaoperacinespecialdelaclase quesellamaautomticamentedurantelacreacin delobjeto.EnC++esfcilmentereconocibleporque tieneelmismonombrequelaclaseclass Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: // Constructor Cuenta(char *anumero, char *atitular, float asaldo, float ainteres); void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); ...19
ClasesdeObjetos
Laimplementacindelconstructordenuestraclase seralasiguiente:Cuenta::Cuenta(char *anumero, char *atitular, float asaldo, float ainteres) { strcpy(numero, anumero); strcpy(titular, atitular); saldo = asaldo; interes = ainteres; }
Muchasvecesresultamuyinteresantedefinirvarios mtodosdeinicializacinparaunaclase.Porejemplo, unaclaseImagenpuedeserinicializadadevarias formas,utilizandomltiplesconstructores,esdecir, sobrecargandoelconstructor20
Ejemplos:
ClasesdeObjetos
Crearunaimagenvaca,indicandoeltamaoenpixelsyelnmerodecolores. Crearunaimagenrecuperndoladesdeunficheroendisco,dadoelnombredel mismo Crearunaimagenmedianteunaoperacinpegndoladesdeelportapapelesdel sistemaclass Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: // Constructor para cualquier tipo de cuentas Cuenta(char *anumero, char *atitular, float asaldo, float ainteres); // Constructor para cuentas corrientes (interes = 1) Cuenta(char *anumero, char *atitular, float asaldo); void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos() { return saldo < 0; } float verSaldo() { return saldo; } };21
Paraquelasobrecargade funcionespuedarealizarse, lalistadeargumentosdebe serdiferente(enelnmeroo tipodelosargumentos)
ClasesdeObjetos
Laimplementacindelsegundoconstructorsera:Cuenta::Cuenta(char *anumero, char *atitular, float asaldo) { strcpy (numero, anumero); strcpy (titular, atitular); saldo = asaldo; interes = 1; }
Vamosaaadiruntercerconstructorparaleerlos datosdelacuentadesdeunficheroclass Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: // Constructor para nuevas cuentas de cualquier tipo Cuenta(char *anumero, char *atitular, float asaldo, float ainteres); //Sigue...22
// Constructor para nuevas cuentas corrientes (interes = 1) Cuenta(char *anumero, char *atitular, float asaldo); // Constructor para cuentas ya existentes, almacenadas en disco Cuenta(char *anumero); void ingreso(float cantidad); void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos() { return saldo < 0; } float verSaldo() { return saldo; } }; Cuenta::Cuenta(char *anumero) { char nombref[80]; strcpy(numero, anumero); strcpy(nombref, anumero); strcat(nombref, ".cnt"); // Abrir el fichero de la cuenta ifstream in (nombref); if (!in) exit (1); // Leer los valores de las variables miembro getline(in, numero); getline(in, titular); in >> saldo; in >> interes; }
ClasesdeObjetos
23
ClasesdeObjetos
UnalimitacindeC++yJavaesquenopueden definirsedosconstructoresquerecibanlosmismos parmetrosaunquesignifiquencosasdistintasPorejemplo,nopodramosaadirunconstructorparacuentasdeahorro(conun intersfijoal8%):Cuenta::Cuenta(char *anumero, char *atitular, float asaldo) { strcpy(numero, anumero); strcpy(titular, atitular); saldo = asaldo; interes = 8; }
Losparmetroscoincidenconlosdelconstructorparacuentascorrientes, portantoelcompiladornopuededistinguirentreambasfuncionesyproducir unerrordecompilacin
24
ClasesdeObjetos
EnellenguajeEiffelestoesposible,yaquecada constructorpuedetenerunnombredistinto:-- Constructor general de la clase Cuenta crear(anumero, atitular: STRING; asaldo: INTEGER; ainteres: REAL) is do ... End -- Constructor para cuentas corrientes (interes = 1) crearCorriente(anumero, atitular: STRING; asaldo: INTEGER) is do ... end -- Constructor para cuentas de ahorro (interes = 8) crearAhorro(anumero, atitular: STRING; asaldo: INTEGER) is do ... end
25
ClasesdeObjetos
Cuandounargumentopuedetomaronounvalor pordefectopuedenutilizarseargumentosporomisin Elnmerodeargumentospordefectopuedevariar, conlacondicindequedaragrupadosalfinaldela listadeparmetrosCuenta::Cuenta(char *anumero, char *atitular, float asaldo, float ainteres = 1) { strcpy(numero, anumero); strcpy(titular, atitular); saldo = asaldo; interes = ainteres; }
26
ClasesdeObjetos
Unconstructorpordefectouomisinesaquelque norequiereargumentos.Lalistadeargumentoseso bienvaca,otodoslosargumentostienenvalorespor omisinasignadosaellosclass Fecha { int dd, mm, aa; public: Fecha(int d=0, int m=0, int a=0):dd(d),mm(m),aa(a){ // Si no se indica una fecha, coger la hora actual if (dd == 0 && mm == 0 && aa == 0) { time_t tiempoActual; struct tm *fechaActual; time(&tiempoActual); fechaActual = localtime(&tiempoActual); dd = fechaActual->tm_mday; mm = fechaActual->tm_mon + 1; aa = fechaActual->tm_year + 1900; } } ... }27
ClasesdeObjetos
Ejemplodeconstructorconlistadeargumentosvacaclass Fecha{ int dd, mm, aa; public: Fecha():dd(1),mm(1),aa(2000){}; ... }
Unconstructorcopiaesaquelquesirveparacrear unobjetoexactamenteigualqueotroCuenta::Cuenta(Cuenta& c) { strcpy(numero, c.numero); strcpy(titular, c.titular); saldo = c.saldo; interes = c.interes; }
Elcompiladorproporcionasiempreunconstructorcopiapordefecto. Esteconstructorsimplementecopialosatributosdelobjetoquesepasa comoargumento(llamandoasusrespectivosconstructorescopia
28
ClasesdeObjetos
FinalizacindeunaclaseDemaneraanlogaalainicializacin,muchas vecesesnecesariorealizarciertastareasantesde ladestruccindeunobjetodeunaclasetrassuuso:Liberacindememoriadinmicaasignadadurantelavidadelobjeto Cierredeficheros,liberacinengeneraldecualquierrecursodelsistema Salvarelcontenidodelobjetoendiscooenunabasededatos
Podrausarseunaoperacincomodestruyeo finaliza,perolosinconvenientesseranlosmismos quelosexistentesenelcasodelainicializacin Loslenguajesorientadosaobjetosproporcionanun tipodeoperacionesespecialesdenominados destructoresdelaclase29
ClasesdeObjetos
Alcontrarioqueenelcasodelosconstructores, existeunnicodestructor,queesinvocado automticamentealdestruirelobjeto EnC++eldestructortieneelmismonombrequela clase,precedidoporelcarcter~(ASCII126)y nuncatieneargumentosenlallamada// Un array dinmico muy simple class ArrayIntDin { int *mem; unsigned tam; public: // Constructor, asignacin de memoria dinmica ArrayIntDin(unsigned atam) { mem = new int[tam = atam]; } ~ArrayIntDin() { delete[] mem; } // Destructor int leer(unsigned pos) { return mem[pos]; } void escribir(unsigned pos, int valor) { mem[pos] = valor; } };30
ClasesdeObjetos
Enelejemplo,trasoperarconunacuenta,seranecesarioquesesalvarade manerapermanenteendisco.Ascuandosevuelvaarecuperar,susaldoydems caractersticassemantendrnjustocomoestabantraslaltimaactualizacin: Vamosaintroducirundestructorquerealiceestastareasclass Cuenta { char numero[20]; char titular[80]; float saldo; float interes; public: // Constructores Cuenta(char *anumero, char *atitular, float asaldo, float ainteres); Cuenta(char *anumero, char *atitular, float asaldo); Cuenta(char *anumero); // Destructor de la cuenta. Salva el estado de la cuenta en disco ~Cuenta(); void ingreso(float cantidad); // Operaciones de la clase void reintegro(float cantidad); void ingresoInteres(); int estaEnRojos() { return saldo < 0; } float verSaldo() { return saldo; } };31
ClasesdeObjetos
Estaeslaimplementacindeldestructor:Cuenta::~Cuenta () { char nombref[80]; strcpy(nombref, numero); strcat(nombref, ".cnt"); // Abrir el fichero de la cuenta para escritura // (Obviamos la comprobacin de errores) ofstream out(nombref); // Escribir los valores de las variables miembro out