PDF de programación - Tema 4 Clases y objetos en C++

Imágen de pdf Tema 4 Clases y objetos en C++

Tema 4 Clases y objetos en C++gráfica de visualizaciones

Actualizado el 21 de Marzo del 2018 (Publicado el 2 de Enero del 2018)
821 visualizaciones desde el 2 de Enero del 2018
106,7 KB
20 paginas
Creado hace 18a (27/04/2006)
Tema 4

Clases y objetos en C++

4.1.

Introducci´on

A lo largo del curso nos hemos encontrado con varias situaciones en las que era necesa-

rio trabajar con datos para los que no exist´ıa un tipo predefinido adecuado. Por ejemplo,

programas que deb´ıan procesar n´umeros racionales, naipes en un juego de cartas, fichas

de clientes, listas de nombres, etc. La soluci´on que hemos adoptado hasta el momento es

definir un nuevo tipo, normalmente una estructura (struct), y definir funciones y proce-

dimientos que procesaran tales estructuras. Esta soluci´on presenta varios inconvenientes

que ilustraremos a continuaci´on.

Supongamos que vamos a escribir un programa C++ en el que necesitamos procesar

fechas. C++ carece de un tipo predefinido adecuado para representar las fechas, de

manera que decidimos definir un tipo TFecha de la siguiente manera:

struct TFecha {

int dia;

// 1..31

int mes;

// 1..12

int anyo;

// 2000...2999

};

Adem´as de definir la estructura TFecha, debemos definir funciones y procedimientos que

soporten operaciones b´asicas sobre este tipo. Por ejemplo, podemos incluir en nuestro

programa las siguientes declaraciones:

// operaciones basicas para el tipo TFecha

bool laborable(TFecha f);

bool festivo(TFecha f);

void manyana(TFecha& f);

1

E.T.S.I. Telecomunicaci´on

Laboratorio de Programaci´on 2

void ayer(TFecha& f);

int dias_entre(TFecha f1, TFecha f2);

Ser´ıa deseable que una vez que hemos definido el tipo TFecha y sus operaciones b´asicas,

este nuevo tipo se pudiera emplear como si fuera un tipo predefinido de C++. Por

desgracia, esto no es as´ı. La soluci´on adoptada presenta una serie de inconvenientes.

En primer lugar, no hay forma de prohibir a otros programadores el acceso a los

componentes de la estructura que implementa el tipo TFecha. Cualquier programador

puede acceder de forma directa a cualquier campo y modificar su valor. Esto puede hacer

los programas m´as dif´ıciles de depurar, pues es posible que estos accesos directos a la

estructura no preserven la consistencia de los datos. Por ejemplo, un programador puede

escribir una funci´on como la siguiente:

void pasado_manyana(TFecha& f)

{

}

f.dia= f.dia+2;

Es f´acil ver que la funci´on pasado_manyana puede dar lugar a fechas inconsistentes como

el 30 de febrero de 2002. El programador ha olvidado que “pasado ma˜nana” puede ser “el

mes que viene” o incluso “el a˜no que viene”. Si todos los accesos directos a los campos

de TFecha los realiza el programador que defini´o el tipo y nos encontramos con una fecha

inconsistente, el error debe estar necesariamente localizado en alguna de las operaciones

b´asicas del tipo.

Otro problema que se deriva de permitir el acceso directo a la estructura es que los

programas se vuelven m´as dif´ıciles de modificar. Supongamos que decidimos alterar la

estructura interna del tipo TFecha modificando el tipo del campo mes, a˜nadiendo un tipo

enumerado para los meses:

enum TMes {enero, febrero,..., noviembre, diciembre};

struct TFecha {

int dia;

// 1..31

TMes mes;

// enero...diciembre

int anyo;

// 2000...2999

};

Si otro programador hab´ıa escrito una funci´on como la siguiente:

2

Clases y objetos en C++

void mes_que_viene(TFecha& f)

{

}

f.mes= (f.mes % 12 ) + 1;

´esta dejar´a de compilar. Si todos los accesos directos a TFecha se han realizado en las

operaciones b´asicas, s´olo ´estas necesitan ser modificadas.

Finalmente, otro inconveniente de definir un nuevo tipo mediante una estructura y

una serie de operaciones b´asicas es la falta de cohesi´on. No hay forma de ver el tipo

TFecha como un todo, como un conjunto de valores y una serie de operaciones b´asicas

asociadas. En concreto, no hay forma de establecer expl´ıcitamente la relaci´on entre el tipo

TFecha y sus operaciones b´asicas. Suponemos que la funci´on festivo es una operaci´on

b´asica del tipo TFecha simplemente porque tiene un argumento de este tipo. Pero, ¿c´omo

sabemos si pasado_manyana es o no una operaci´on b´asica? Y si definimos una funci´on

que toma argumentos de diferentes tipos... ¿a cu´al de esos tipos pertenece la funci´on?,

¿de cu´al de ellos es una operaci´on b´asica?

El prop´osito de las clases en C++ es facilitar al programador una herramienta que le

permita definir un nuevo tipo que se pueda usar como un tipo predefinido de C++. En

particular, las clases de C++ facilitan un mecanismo que permite prohibir los accesos

directos a la representaci´on interna de un tipo, as´ı como indicar claramente cu´ales son

las operaciones b´asicas definidas para el tipo.

4.2. Revisi´on de conceptos b´asicos

4.2.1.

Interfaz vs. Implementaci´on

Al definir una clase deben separarse claramente por una parte los detalles del funcio-

namiento interno de la clase, y por otra la forma en que se usa la clase. Esto lo hemos

hecho en pseudo-c´odigo distinguiendo entre el interfaz y la implementaci´on de la clase:

INTERFAZ CLASE NombreClase

METODOS

...

FIN NombreClase

IMPLEMENTACION CLASE NombreClase

ATRIBUTOS

3

E.T.S.I. Telecomunicaci´on

Laboratorio de Programaci´on 2

...

METODOS

...

FIN NombreClase

El interfaz puede entenderse como las instrucciones de uso de la clase, mientras que la

implementaci´on contiene (y oculta) los detalles de funcionamiento.

4.2.2.

Implementador vs. Usuario

Es muy importante recordar que un programador puede desempe˜nar dos papeles di-

ferentes respecto a una clase: implementador y usuario. El programador implementador

de una clase se encarga de definir su interfaz (cabecera de los m´etodos) y de desarro-

llar los detalles internos de su implementaci´on (atributos y cuerpo de los m´etodos). El

implementador de una clase tiene acceso total a los objetos de esa clase.

Por otro lado, el programador usuario s´olo puede utilizar los objetos de una clase

aplic´andoles los m´etodos definidos en su interfaz. El usuario no tiene acceso directo a los

detalles internos de la implementaci´on.

En las siguientes secciones, veremos c´omo definir e implementar clases en C++ (punto

de vista del implementador) y c´omo usar una clase C++ (punto de vista del usuario).

4.3. Definici´on de clases en C++

Desgraciadamente, la divisi´on entre interfaz e implementaci´on no es tan limpia en

C++ como en el pseudo-c´odigo. Las clases se definen en C++ mediante una construcci´on

class dividida en dos partes: una parte privada (private) que contiene algunos detalles

de la implementaci´on, y una parte p´ublica (public) que contiene todo el interfaz.

class NombreClase {

private:

// implementacion de la clase

// solamente los atributos

// interfaz de la clase

public:

};

En la parte privada de la construcci´on class aparecen s´olo los atributos de la clase y

algunos tipos intermedios que puedan ser necesarios. En C++, la implementaci´on de los

4

Clases y objetos en C++

m´etodos de la clase se facilita aparte. En la parte p´ublica, suelen aparecer solamente las

declaraciones (cabeceras) de los m´etodos de la clase. Por ejemplo, la siguiente es una

definici´on de la clase CComplejo que representa n´umeros complejos:

class CComplejo {

private:

// atributos

double real, imag;

// los metodos se implementan aparte

public:

void asigna_real(double r);

void asigna_imag(double i);

double parte_real();

double parte_imag();

void suma(const CComplejo& a, const CComplejo& b);

};

Los campos real e imag son los atributos de la clase y codifican el estado de un objeto

de la clase CComplejo. Puesto que los atributos est´an declarados en la parte privada de

la clase, forman parte de la implementaci´on y no es posible acceder a ellos desde fuera

de la clase. Su acceso est´a restringido: s´olo se puede acceder a ellos en la implementaci´on

de los m´etodos de la clase.

Los m´etodos que aparecen en la parte p´ublica forman el interfaz de la clase y describen

su comportamiento; es decir, las operaciones que podemos aplicar a un objeto del tipo

CComplejo. En particular, con estos m´etodos podemos asignar valores a las partes real e

imaginaria, leer las partes real e imaginaria, y sumar dos numeros complejos.

4.4.

Implementaci´on de m´etodos en C++

Como comentamos anteriormente, la implementaci´on de los m´etodos de una clase en

C++ se realiza fuera de la construcci´on class {...}. La sintaxis de la definici´on de un

m´etodo es similar a la de la definici´on de una funci´on (o procedimiento), excepto que el

nombre del m´etodo debe estar precedido por el nombre de la clase de la que forma parte:

void CComplejo::asigna_real(double r)

{

}

// cuerpo del metodo...

5

E.T.S.I. Telecomunicaci´on

Laboratorio de Programaci´on 2

Como puede apreciarse, el m´etodo asignar_real no recibe ning´un argumento de tipo

CComplejo. ¿C´omo es posible entonces que este m´etodo sepa qu´e n´umero complejo tiene

que modificar? La respuesta es que todos los m´etodos de la clase CComplejo reciben

como argumento de entrada/salida impl´ıcito el complejo al que se va a aplicar el m´etodo.

Surge entonces la siguiente pregunta: si este argumento es impl´ıcito y no le hemos dado

ning´un nombre, ¿c´omo accedemos a sus atributos? La respuesta en este caso es que

podemos referirnos a los atributos de este par´ametro impl´ıcito simplemente escribiendo

los nombres de los atributos, sin referirnos a qu´e objeto pertenecen. C++ sobreentiende

que nos referimos a los atributos del argumento impl´ıcito. As´ı, el m´etodo asigna_real

se implementa como sigue:

void CComplejo::asigna_real(double r)

{

}

real= r;

donde el atributo real que aparece a la izquierda de la asignaci´on es el atributo del

argumento impl´ıcito. Incluso un m´etodo como parte_imaginaria, que aparentemente

no tiene argumentos, recibe este argumento impl´ıcito que representa el objeto al que se

aplica el m´etodo:

double CComplejo::parte_imaginaria()

{

}

return imag; // atributo imag del argumento implicito

Por otro lado, un m´etodo puede recibir argumentos expl´ıcitos de la clase a la que per-

tenece. Por ej
  • Links de descarga
http://lwp-l.com/pdf8140

Comentarios de: Tema 4 Clases y objetos en C++ (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad