|
Tema
18 Clases:
Definiciones
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Teoría:
Objetos
miembros de otros objetos
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Una
clase, a semejanza de una estructura, puede contener
variables miembro que sean objetos de
otra clase definida por el usuario. Ésta es
una relación de pertenencia que no tiene nada
que ver con la herencia, que se explicará en
el capítulo siguiente. El constructor de la
clase que contiene objetos de otras clases debe llamar a los
constructores de los objetos contenidos, si no se quiere
que se utilicen los constructores por defecto. Esta
llamada es muy similar a la de los constructores de las clases derivadas,
como se verá más adelante. Considérese el siguiente
ejemplo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Clase_Continente::Clase_Continente
(Lista de argumentos)
: Clase_Contenida1 (Lista de argumentos),
Clase_Contenida2 (Lista de argumentos), otros inicializadores
{
Asignación
de otras variables;
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Los
constructores de las clases contenidas se llaman
de la misma forma que los inicializadores de las variables
miembro ordinarias: después del carácter dos puntos
(:) que aparece tras los argumentos, separados por comas, y antes
del bloque del constructor. Puede considerarse que los constructores
no son más que inicializadores especializados.
A
continuación se va a presentar un ejemplo. La clase persona
tiene tres variables miembro privadas: el nombre, el número
de DNI y la fecha de nacimiento. A su vez la fecha de nacimiento
es un objeto de la clase Date, que tiene tres variables
miembro: el día, mes y año de nacimiento.
Como la fecha de nacimiento no se puede cambiar, el correspondiente
objeto en la clase persona se ha declarado como const.
La
clase Date dispone de funciones miembro públicas
para obtener el día, mes y año de cualquier objeto
de dicha clase, así como de funciones para cambiar esas variables
miembro (que no se pueden utilizar con un objeto const).
La declaración de la clase Date con funciones
inline es como sigue:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
fichero date.h
// definición de la clase Date
class Date {
private:
int
day;
int month;
int year;
public:
//
constructor con valores por defecto
Date(int dia=1, int mes=1, int anio=1900) :
day(dia), month(mes), year(anio) {}
int getDay() const { return day; }
int getMonth() const { return month; }
int getYear() const { return year; }
// función para calcular los años completos entre
dos fechas
friend int ElapsedYears(const Date&, const Date&);
// Si el objeto no es const, añadir estas funciones miembro:
void setDay(int dia) { day=dia; }
void setMonth(int mes) { month=mes; }
void setYear(int anio) { year=anio; }
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Las
funciones getDay(), getMont() y getYear() han sido
declaradas como const. Esto quiere decir que son funciones
que no modifican las variables miembro, es decir funciones
de sólo lectura. La palabra const debe
figurar tanto en la declaración como en la definición,
después de cerrar el paréntesis de los argumentos
y antes del cuerpo de la función.
A
continuación se incluye la declaración de la clase
persona, que incluye también tres funciones
miembro inline para acceder a las variables miembro
privadas. Obsérvese que la fecha de nacimiento se ha definido
como const (resaltado con negrita en el listado de
la definición),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
fichero persona.h
#include <iostream.h>
#include "date.h"
class persona {
private
:
char
nombre[25];
long DNI;
const Date fechaNac;
public:
//
constructor
persona(char*, long, Date);
char* getNombre(void)
{ return nombre; }
long getDNI(void)
{ return DNI; }
Date getFechaNac(void)
{ return fechaNac; }
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
El
fichero persona.cpp que se muestra a continuación
contiene la definición del constructor de la clase persona.
Dicho constructor tiene valores por defecto para los
tres argumentos. Se puede observar que tanto el DNI como
la fecha de nacimiento toman valor por medio de inicializadores
y no de sentencias de asignación. En el caso del DNI
esto es opcional, pero en la fecha de nacimiento es
obligatorio ya que es un objeto const que no puede
figurar a la izquierda en una sentencia de asignación. Nótese
también que el tercer argumento se puede inicializar a partir
de tres valores ya que existe un constructor Date que
puede tomar estos parámetros. Es importante notar la forma
en la que C++ hace definir el tercer argumento y del segundo inicializador,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
Fichero persona.cpp
#include "persona.h"
#include <string.h>
//
definición del constructor con valores por defecto
persona::persona(char* name = "", long dni = 0, Date birth=(1,1,1970)
)
//
inicializadores
: DNI(dni), fechaNac(birth)
{
strcpy(nombre,
name);
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Finalmente
se incluye el fichero lista2.cpp, que contiene un
programa principal que hace uso de las clases Date y persona.
Se definen dos personas, una definiendo directamente un objeto y
la otra mediante un puntero y reserva dinámica de memoria.
Obsérvese cómo se pasa al constructor de
persona la fecha de nacimiento. En el mismo fichero que
el programa principal está la función ElapsedYears()
que calcula los años completos transcurridos
entre dos objetos Date que se le pasan como argumentos.
Como esta función se ha declarado como función friend,
su definición se ha incluido en el mismo fichero que el programa
principal.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
fichero lista2.cpp
#include <iostream.h>
#include "persona.h"
int
ElapsedYears(const Date& hoy, const Date& birth);
void
main(void)
{
//
ver cómo se inicializa un objeto Date que es const
persona* m = new persona("Maria", 26429764, Date(1,
2, 1980));
persona i("Ignacio", 25190578, Date(13, 4, 1992));
Date hoy(13,4,1998);
cout << m->getNombre() << " tiene " <<
ElapsedYears(hoy, m->getFechaNac()) <<
" agnos" << endl;
cout << i.getNombre() << " tiene " <<
ElapsedYears(hoy, i.getFechaNac()) <<
" agnos" << endl;
cout << "Ya he terminado." << endl;
}
//
Función para calcular los años completos entre dos
fechas
int ElapsedYears(const Date& hoy, const Date& birth)
{
int
years = hoy.year - birth.year;
if ((birth.month <= hoy.month) && (birth.day <=
hoy.day))
return years;
else
return (years-1);
}
|
|
|
|
|
|
|
|