1. Índice
● Introducción
● Declaración de una clase
● Encapsulación
● Representación gráfica de una clase
● Constructores y destructores
Tema 2. Programación Orientada a Objetos ● Creación y eliminación dinámica de objetos
● Paso y retorno de objetos a funciones
Programación II ● Otras características
– Operador asignación
– Operador this
– Atributos estáticos
– Métodos constantes
● Composición
● Bibliografía
● Ejemplos y ejercicios
Programación II 1 Programación II 2
Introducción Introducción II. Historia I.
● Programación orientada a objetos: ● Las técnicas de programación han considerando distintas
– ¿Qué es? entidades a lo largo del tiempo, las cuales cada vez tienen un
–
mayor nivel de abstracción. Parece muy lejano la
¿Para qué sirve?
programación en binario, pero solamente han transcurrido 50
– ¿Por qué? años.
– ¿Cómo surgió? ● Se pueden clasificar:
– ¿Dónde debe usarse?
– Prehistoria de la programación (maquina)
– ¿Cómo debe usarse?
– Programación estructurada
– .....
– Programación procedimental
● La programación orientada a objetos ha surgido con motivo – Programación Modular
de una evolución en la forma de desarrollar proyectos
– Los tipos abstractos de datos
software.
– Programación orientada a objetos
● No se trata de una nueva metodología, apareció en los años
60 con el lenguaje Simula-67. Muchos de los lenguajes
actuales utilizan este paradigma.
Programación II 3 Programación II 4
2. Introducción III. Historia II Introducción III. Historia II
● Programación Estructurada ● Programación Procedimental
– Introducción de una serie de estructuras de control básicas – Se basa en la idea de descomponer los programas en funciones que
● Secuencia resuelvan el problema.
● Selección – Una vez determinadas las funciones, para la solución del problema
solamente se deben realizar llamadas a estas funciones.
● Iteración
– Se debe definir separadamente las estructuras de datos que manejan
– De este modo se construyen programas más legibles y fáciles de
mantener. los programas.
– Inconvenientes:
– Sin duda alguna supuso un cambio bastante importante, pero los
problemas complejos son difíciles de mantener. ● Realizar una descomposición procedimental para resolver problemas
complejos es muy difícil.
● Dificultad de reutilización
– Lenguajes procedimentales: C, Pascal, fortran, ....
Programación II 5 Programación II 6
Introducción IV. Historia III. Introducción V. Historia IV
● Programación modular ● Tipos abstractos de datos
– La idea es dividir el problema en módulos independientes qué – El objetivo es definir cuales son las estructuras de datos y definir sus
representen una caja negra donde cada módulo resuelva una parte del operaciones de manipulación.
problema. – Se basa en la programación modular y el objetivo es conseguir la
– Dentro de cada uno de los módulos se incluyen los procedimientos y encapsulación del código y datos.
funciones que proporcionen la funcionalidad deseada de ese módulo. – El objetivo es que el acceso a los datos se produzca mediante las
– Con esta técnica el problema puede ser resueltos por distintas funciones aunque realmente no se consigue dicho objetivo.
personas, donde cada una implementa sus módulos. – Algunos autores clasifican esta técnica como la antesala de la
– Con esta programación aparecen otros conceptos: programación orientada a objetos.
● Compilación separada – El principal inconveniente radica en que conceptos como herencia,
● Interfaz de utilización de un módulo polimorfismo no se pueden contemplar en esta técnica.
● Se puede dividir el problema en módulos más comprensibles
– Inconvenientes:
● Realizar una descomposición procedimental para resolver problemas
complejos es muy difícil.
● Dificultad de reutilización
Programación II 7 Programación II 8
3. Introducción VI. Historia V. Introducción VII. Historia VI.
● Programación orientada a objetos ● Nomenclatura usada:
– Metodología basada en la idea natural de la existencia de un mundo
lleno de objetos. Todo es objeto software.
Conceptos empleados en Técnicas Tradicionales C++
– El objetivo es identificar los objetos y definir sus comportamientos. las Técnicas Orientadas a
Objetos
– La solución al problema se consigue mediante una secuencia de Métodos Procedimientos, funciones o Función
subrutinas miembro
pasos de mensajes entre los objetos. Variables Instancia Datos Miembros
Objeto , instancia Variable Objeto
– Ventajas: Mensajes Llamadas a procedimientos y Llamada a
funciones función
● Favorece el diseño de sistemas software complejos. Clases Tipos Abstractos de Datos Clases
● Reusabilidad: Reutilización del código Herencia No existe técnica similar Derivación
Subclase No existe técnica similar Clase
● Extensibilidad: Extensión del código derivada
Llamadas bajo control del Llamadas bajo el control del
● Reducir el coste de desarrollo y mantenimiento sistema programador
programa=sistema de programa=secuencia de
● Mejorar la productividad de los programadores objetos interactivos instrucciones
● Sistemas más robustos y estables.
– Otros conceptos: herencia, polimorfismo, vinculación dinámica,....
Programación II 9 Programación II 10
Declaración de una clase Declaración de una clase II
● Antes de crear un objeto deberemos establecer su plantilla o class Nombre_clase {
formato -> Clase. Ej: Punto, vehículo, televisor, persona //atributos
● Para cada clase se deben describir sus características y su //Miembros
comportamiento. };
● Una clase es la especificación de un tipo de objeto que se
Ejemplo. Clase Punto
encuentra formado:
–
class Punto {
Sus características, tanto físicas como lógicas--> Atributos
–
int _x, _y;
Su comportamiento, operaciones que se pueden realizar en una clase
--> Métodos o funciones (Miembro en C++) void dibujar ();
● Debemos diferenciar claramente entre: int leer_x();
– Clase--> Plantilla de un objeto int leer_y();
– Objeto --> Ejemplares o variables de una clase. void dar_x(int x);
void dar_y(int y);
};
Programación II 11 Programación II 12
4. Declaración de una clase III Declaración de una clase IV
● Implementación de las funciones miembros: Dos tipos: ● Cada variable que se declara de una clase se conoce como
– Funciones miembros insertadas. En la propia definición se realiza su objeto de una clase.
implementación.
● Todos los objetos de una misma clase tienen las mismas
– Funciones miembros fuera de la clase. Se implementan fuera de la
definición de la clase. Tipo Nom_Clase::Func_Miem(Parametros) {};
características y miembros pero con diferentes valores.
class Punto { ● Declaración de un objeto:
int _x, _y; //Atributos
void inicializar () { _x=0;_y=0;}; //Función miembro insertada
Nombre_Clase obj1, obj2, ....objN;
int leer_x() {return _x;} //Función miembro insertada
int leer_y() {return _y;} //Función miembro insertada
● Ejemplo: Queremos declarar 3 objetos puntos:
void dar_x(int x);
void dar_y(int y);
Punto punto_1, punto_2, punto_3;
};
void Punto::dar_x (int x) { void Punto::dar_y (int y) { Implementación de las
funciones miembros
this->_x=x; this->_y=y;
externas a su definición
} }
Programación II 13 Programación II 14
Declaración de una clase. V Declaración de una clase VI
using namespace std; ● Los objetos se manipulan mediante el paso de mensajes.
int main() {
● El funcionamiento de una aplicación OO se realiza mediante
Punto p; //Declaramos un objeto de tipo punto
el paso de mensajes entre las distintas instancias del mismo.
int m,n;
● De este modo:
cout<<”Escribe la coordenada X:”<<endl; – Los mensajes inician acciones
cin >>m; – Los mensajes se envían a objetos
cout<<”Escribe la coordenada y:”<<endl; – Un objeto recibe mensajes y ejecuta métodos: ocultación de
cin >>n; información
p.dar_x(m);
p.dar_y(n);
cout<<”La coordenada X es: ”<< p.leer_x()<<endl;
cout<<”La coordenada Y es: ”<< p.leer_y()<<endl;
return 0;
}
Programación II 15 Programación II 16
5. Encapsulación I Encapsulación II
● Uno de los pilares básicos de la POO es la encapsulación de ● La definición anterior se ve modificada:
los datos. El acceso a los datos de una clase deben realizarse class Punto {
de forma controlada, protegiéndolos de acceso no
autorizados. private:
int _x, _y;
● De este modo, existe una ocultación de la información fuera
public:
de la clase.
void dibujar();
● Los atributos deben estar ocultos --> Privado, aunque C++ .....
permite declararlos público, nunca lo usaremos.
};
● Las funciones miembros permiten el acceso a los atributos
--> Pública, aunque pueden existir funciones miembros
● Los modificadores de acceso son:
privadas que son usadas por las públicas. – Public: Su acceso se puede realizar desde fuera de la clase
– Private: Su acceso esta limitado dentro de la clase.
● De este modo se busca que el acceso a los datos sea
controlado y sólo se puede realizar mediante las funciones – Protected: Se verá posteriormente
miembros. ● Ejemplo: Definir las siguientes clases: Vehículo, persona y
círculo.
Programación II 17 Programación II 18
Encapsulación III Encapsulación IV. Ejemplo
● A los elementos privados sólo se pueden acceder desde ● Ejemplo Clase Persona.
dentro de la clase, mientras que a lo público se accede desde class Persona {
cualquier objeto.
private:
● Los atributos de una clase son datos de tipos previamente char _nombre[30];
definidos u objetos de otras clases. char _nif[10];
int _edad;
● Dentro de la clase public:
– Se puede acceder a los atributos void inicializar (char *nombre, char * nif,int edad);
– Se puede acceder a los métodos públicos y privados void leer_nombre(char *nombre);
void leer_nif(char *nif);
● Desde un objeto void leer_edad(int edad);
– No se puede acceder a los atributos privados char * dar_nombre();
char * dar_nif();
– No se puede acceder a las funciones miembros privadas int dar_edad();
– Sólo se puede acceder a las funciones miembros públicas void mostrar();
};
– Se utiliza el paso de mensaje: objeto.mensaje
Programación II 19 Programación II 20
6. Encapsulación V Representación gráfica
● Convenios de denominación ● Para representar gráficamente los elementos de los programas
– Los identificadores se escribirán en general en minúsculas, a OO y sus relaciones vamos a utilizar los diagramas UML que
excepción, en los casos que se indique, de ciertas letras. son usados dentro de la Ingeniería del Software.
– Las clases comenzarán por mayúscula: Clase, Punto, Circulo. ● Según se vayan mostrando los distintos conceptos de OO se
– Los atributos comenzarán por subrayado: _x, _y. presentará su representación UML.
– Los métodos comenzarán por minúscula. Aquellos que sean ● Representación de una clase
específico de un determinado atributo llevarán un guión: leer_x (),
leer_y(). Punto
– Los objetos comenzarán por minúscula: objeto1, punto. Nombre_Clase _x:int
_y:int
– Los identificadores compuestos por varias palabras: la segunda y
siguientes palabras llevarán su primera letra en mayúscula:
Atributos Inicializar(x:int,y:int):void
dar_x:int
listaPuntos, vectorPuntos. Métodos dar_y:int
leer_x(x:int):void
leer_y(y:int):void
● Se pueden omitir alguna de las secciones o dejarse en blanco
Programación II 21 Programación II 22
Constructores y Destructores Constructores y Destructores II
● Tal y como se ha podido comprobar la declaración de objetos ● Constructor: Función miembro encargada de inicializar las
se realiza de la misma forma que para el resto de las instancias de clase cuando estas son creadas.
variables. ● Los constructores deben tener el mismo nombre que la clase y
● De forma que cuando se necesita, primero se crea la variable nunca puede devolver ningún tipo de dato.
y posteriormente se destruye. ● Los constructores deben definirse dentro de la sección pública,
● Pero en la POO existe una peculiaridad. Cuando se crea un pues sino, no se tendría acceso a los mismos.
objeto se produce una llama de forma automática a un ● Sintaxis:
método especial denominado constructor.
class Nombre_Clase {
● Y cuando se destruye se realiza otra llamada automática al
nombre_clase::nombre_clase(parámetros); //Definición Constructor
destructor.
.....
● Si nosotros no lo proporcionamos, el compilador generará };
unos por defecto, pero como veremos posteriormente esta
nombre_clase::nombre_clase(parámetros) { //Implementación
situación no es realmente conveniente.
}
Programación II 23 Programación II 24
7. Constructores y Destructores III Constructores y Destructores IV
● Ejemplo ● A veces es necesario poder inicializar los objetos de distintas
class Punto { formas. Por ejemplo, disponer un constructor que los
public:
inicialice a un valor por defecto o un constructor que recibe
por parámetros los valores de cada uno de los atributos. -->
Punto(); //Constructor. Definición.
Sobrecarga de funciones.
.....
};
● La sobrecarga de funciones nos permite definir funciones con
el mismo nombre pero con distinta signatura (número y tipo
Punto::Punto() { //Constructor. Implementación
de parámetros).
cout << “Estoy en el constructor”<< endl;
_x=0; _y=0;
● Clasificación de los constructores
– Constructor predeterminado: No tiene ningún argumento.
}
– Constructor Parametrizado: Reciben por parámetro los valores
.....
iniciales de los atributos de la clase. Se pueden definir varios
int main() { constructores parametrizados para una clase.
Punto p; //Se produce la llamada al constructor automáticamente
.....
};
Programación II 25 Programación II 26
Constructores y Destructores V Constructores y Destructores VI
Class Punto {
Punto(); //Constructor por defecto ● En las clases debe existir un constructor por defecto, que no
Punto(int a, int b); //Constructor parametrizado *** tenga argumentos, y este se invoca siempre que se crea un
Punto (int a); //Constructor parametrizado objeto (si no es con parámetros).
.....
};
● Si no se proporciona uno, el compilador genera
int main() {
automáticamente un constructor por defecto.
Punto p; //Llamada constructor por defecto
Punto p1(5); //Llamada constructor parametrizado
Punto p2 = Punto(2,3); //Llamada constructor parametrizado
● Este constructor funcionará correctamente siempre y cuando
Punto p3[6]; //Vector de puntos. Constructor parametrizado para cada posición
no tengamos un atributo dinámico dentro de la clase. En este
caso se debe implementar un constructor por defecto, debido
};
a que en éste se deberá realizar la reserva de memoria.
***Cuidado: Si se hubiera usado int a=0, int b=0, daría problema de anbigüedad pues el
compilador no sabría cual de los constructores tiene que usar (Entre el 1 y el 2). Si se
quiere valores por defecto sobraría el último constructor.
Programación II 27 Programación II 28
8. Constructores y Destructores VII Constructores y Destructores VIII
● Destructores: Función miembro encargada de “destruir” ● Constructor copia
toda la información asociada a una instancia de una clase, – Existe otro constructor muy importante en la OO, el cual es utilizado
principalmente si se había reservado memoria. cuando se crea un objeto a partir de otro.
● Igual que el constructor: – Igual que con el constructor por defecto, si no se proporciona uno el
compilador genera uno.
– Es invocado automáticamente por el compilador
– El constructor copia por defecto copia bit a bit los atributos de la
– No tiene argumentos instancia copiada.
● Importante: Sólo puede existir uno por clase – Este constructor funciona correctamente siempre y cuando no
● Sintaxis: existan atributos que se accedan mediante punteros, pues si se copia
bit a bit el atributo de los dos objetos apuntarían a la misma
~Nombre_Clase(); dirección.
● Ejemplo: ● Ejemplo:
~Punto(); Punto p(10,10); //Constructor parametrizado
~Persona(); Punto p2=p1; //Inicialización por copia. Se crea p2 a partir de p1
Punto p3(p2); //Constructor copia. Se crea p3 a partir de p2
Programación II 29 Programación II 30
Constructores y Destructores IX Constructores y Destructores X
● El constructor copia se utiliza:
– Cuando se crea un objeto a partir de otro (Casos anteriores)
– Cuando a una función se le pasan objetos por valor.
void fx (Punto p) {......}
Persona p1; Persona p1;
Juan Juan
– Cuando una función retorna un objeto como valor de retorno. Al terminar char * Nombre char * Nombre
la ejecución se crea una copia del objeto que se devuelve.
Punto fx(....) { Persona p2=p1 Persona p2=p1
Punto x;
return x; }
Persona p2; Persona p2;
Juan
● En estos casos, como se crea una copia del objeto bit a bit que char * Nombre char * Nombre
sucede cuando termina el ámbito del primer o segundo objeto y
se llama al destructor y por tanto se libera su memoria? Si los dos
objetos apuntan a la misma dirección? Constructor Copia por defecto Constructor Copia
Programación II 31 Programación II 32
9. Constructores y Destructores XI Constructores y Destructores XII
● Implementación del constructor copia de la clase Persona ● Resumen:
Persona::Persona(const Persona& origen) {
nombre= new char[strlen(origen.mensaje)+1]; Constructor copia
Para cada clase que definamos siempre se crearán los siguientes
strcpy(nombre,origen.nombre);
objetos
}
– Constructor por defecto
– Constructor copia
Persona::Persona (char *nom) {
nombre=new char [strlen(nom)+1]; – Constructor parametrizado (Opcional)
Reserva de memoria en el
strcpy(nombre,nom); constructor – Operador asignación “=” (Se presentará posteriormente)
} – Destructor (Aunque en algunas ocasiones no realice ninguna
Persona::~Persona() { operación)
if (nombre) {
delete [] nombre; Liberación de la memoria
nombre=NULL;
}
}
Programación II 33 Programación II 34
Creación y eliminación dinámica de objetos Creación y eliminación dinámica de objetos II
● Como cualquier otra variable, existen dos formas de crear un ● Como para el resto de variables dinámicas en C++ se utilizan
objeto: los operadores new y delete.
– Estáticamente: Los objetos son creados y destruidos cuando ha ● Un objeto dinámico como cualquier variable dinámica tiene
terminado su ámbito. El compilador controla su ciclo de vida. el siguiente ciclo de vida:
– Dinámicamente: El programador es el encargado de controlar su – Definir el puntero a un objeto
creación y destrucción.
Punto * p; p Punto
X:int
● ¿Porque se necesita objetos dinámicos si con los estáticos y:int
Inicializar(x:int,y:int):void
– Reservar la memoria e inicializar el objeto (Constructor) DarX:int
puedo trabajar bien? DarY:int
LeerX(x:int):void
p= new Punto(); p LeerY(y:int):void
– Sólo se reserva memoria cuando se necesita
– Utilizar el objeto
– Se liberan los objetos cuando ya no se necesitan, mientras que del
otro mecanismo es el compilador quien los libera cuando termina su p->leer_x();
ámbito. – Liberar la memoria reservada por el objeto
● Ejemplo: Para almacenar 100 puntos, existen dos opciones delete (p);
un vector de puntos (se reserva la memoria para 100 puntos)
o mediante programación dinámica, donde según se necesita
Programación II
un punto se reserva memoria para él. 35 Programación II 36
10. Creación y eliminación dinámica de objetos III Creación y Eliminación dinámica de objetos IV
● Vector de objetos. Dos formas:
– Estática: Punto p[10]; ● Precauciones a tener con los punteros:
– Dinámica. Utilizando los operadores new y delete. Dos soluciones. – Siempre reservar memoria cuando se vaya a usar. Si se intenta
● Primera acceder al contenido apuntado por un puntero sin haber reservado
–
memoria puede ser catastrófico.
Punto * p[2];
– p[0]= new Punto(4,4); //Cualquier otro constructor
– p[0]->leer_x(); – Intentar liberar dos veces un puntero
– cout<<"La coordenada X es: "<< p[0]->leer_x()<<endl;
– cout<<"La coordenada Y es: "<< p[0]->leer_y()<<endl;
– Intentar liberar un puntero para el cual no se ha liberado memoria
– delete p[0];
● Segunda
– Punto * p1; – No liberar el espacio reservado
– p1=new Punto[2]; //Se esta llamando al constructor por defecto
– p1[0].leer_x();
– cout<<"La coordenada X es: "<< p1[0].leer_x()<<endl;
– cout<<"La coordenada Y es: "<< p1[0].leer_y()<<endl;
Programación II – delete []p1; 37 Programación II 38
Paso y retorno de objetos a funciones Paso y retorno de objetos a funciones II
● Los objetos como cualquier otra variable se pueden pasar a ● Paso de objetos por valor:
las funciones. Existen principalmente dos formas: – Igual que con las variables se produce una copia del objeto
– Por valor: El compilador genera una copia de la variable y es – Importante: Esto implica una llamada al constructor copia y una
utilizada en la función. llamada al destructor cuando finaliza su ámbito.
– Por referencia: No se le pasa la variable sino una referencia de la – Problemas:
misma (más eficiente y permite modificar el contenido). Dos formas:
● Si no tenemos definido el constructor copia y se ejecuta el por defecto,
● Como puntero (Heredado de C) se tienen problemas con atributos a punteros.
● Como referencia (C++) ● Además parece poco eficiente pues se tiene que crear un objeto y
Ejemplo (int x, int *y, int &z) destruirlo.
● Los objetos pueden ser pasados mediante estos tres métodos. – Solución:
A continuación se exponen las ventajas e inconvenientes de
● Usar paso por referencias constantes para pasar objetos por valor.
cada uno de ellos.
Programación II 39 Programación II 40
11. Paso y retorno de objetos a funciones III Paso y retorno de objetos a funciones IV
● Paso por referencia (retorno por argumento) ● Funciones que retornan objetos. Dos mecanismos:
– Con este método no se produce una copia del objeto en su invocación – Por valor.
sino que se pasa una referencia del objeto. Ventajas: – Por referencia (Puntero y referencias).
● Eficiencia
● En ambos casos, se deben tener ciertas precauciones y
● Permite la modificación del objeto
asegurarse de:
– Inconveniente:
– Tener un constructor copia
● En ocasiones nos puede interesar solo tener acceso de lectura al objeto y
no de modificación. --> Paso de referencia constante – Tener un operador asignación
class Punto { – Nunca devolver un objeto local creado en la función miembro:
...... ● Se recomienda devolver un objeto por argumento, pues
Punto(const Punto &P); /*Constructor copia. Utiliza la palabra reservada const muchos de los problemas originados mediante “return”
para que no se pueda modificar el objeto P. Paso por referencia constante. Si
se intenta cambiar, el compilador da un fallo de compilación.*/
se resuelven.
void Sumar_Punto (Punto& p); /*El objeto p puede modificarse dentro de la
función.*/
}
Programación II 41 Programación II 42
Paso y retorno de objetos a funciones V Operador asignación
● Ejemplo: ● Cuando se realiza una asignación entre objetos se debe tener
Punto * Punto::suma(Punto *p) { Punto& Punto::suma(Punto &p) { mucho cuidado, pues como se mostrará pueden existir
Punto *result;
int x=p->leer_x(); int x=p.leer_x();
problemas. Dos casos:
int y=p.leer_y();
int y=p->leer_y(); – Asignación de dos objetos estáticos con atributos dinámicos
result->dar_x(this->_x + x);
p->dar_x(this->_x + x); result->dar_y(this->_y + y);º – Asignación de objetos dinámicos
return result; //ERROR muy grave
p->dar_y(this->_y + y); }
return p; void main() {
● En ambos casos el problema es el mismo, pues al realizar la
}
Punto p1,p2(4,4);
Punto *r1=p1.suma(&p2); //Primer tipo
asignación los punteros se copian bit a bit y apuntan a la
Punto& Punto::suma(Punto &p) {
Punto r2=p1.suma(p2); //Segundo tipo misma dirección. Si se liberará o modificará cualquiera de
Punto *r3=p1.suma(p2); //ERROR
int x=p.leer_x(); } ellos el otro se vería seriamente afectado.
int y=p.leer_y(); ● Solución:
p.dar_x(this->_x + x); – Objetos estáticos con atributos dinámicos: Operador de asignación
p.dar_y(this->_y + y);
– Objetos dinámicos: Usar el constructor copia
return p;
}
Programación II 43 Programación II 44
12. Operador asignación II Operador Asignación III
● Primer caso. Objetos estáticos ● Segundo Caso. Asignación de objetos dinámicos
– Para todas las clases se encuentra definido por defecto el operador – Ejemplo del problema:
asignación que es utilizado automáticamente por el compilador cuando se Punto *p, *p2;
tiene una sentencia similar a p2 = p1;
p=new Punto(4,5);
– Si tenemos atributos punteros, sobrecargar el operador asignación p2=p; //Ambos punteros apuntan a la misma dirección !!!!!!!!!!
● Ejemplo: delete p2; //¿Qué sucede con p??
Punto& operator= (const Punto & p); //Definición
– SOLUCIÓN:
Punto& Punto::operator= (const Punto & p) { //Implementación
this->_x=p._x;this->_y=p._y; return *this;
● El problema radica que no se ha reservado memoria para el segundo
puntero. Solución mediante el constructor copia.
}
Punto *p, *p2;
● El objeto que figura a la izquierda del = es el objeto que recibe el p=new Punto(4,5);
mensaje. El mensaje es el operador asignación. El objeto de la p2=new Punto (*p); //Inicialización por copia.
derecha es el objeto origen de la copia.
● La función termina devolviendo el propio objeto receptor.
● Siempre que exista un atributo con puntero se debe generar esta
Programación II
función miembro. 45 Programación II 46
Operador this Atributos estáticos
● El operador this es utilizado para referirse al objeto actual. Se ● Hasta ahora cada objeto tiene su propio conjunto de atributos.
utiliza en cualquier función miembro de la clase y el Sin embargo en algunas ocasiones nos puede interesar que
compilador genera este puntero automáticamente en el los objetos de una clase compartan un mismo atributo –>
proceso de compilación. Atributos estáticos.
● Se trata de un operador fantasma que siempre recibe un – Por ejemplo si se quieren contar cuantos objetos hay declarados de
puntero a un objeto, que es el actual. una clase.
● De este modo en cualquier función miembro se puede usar
● De este modo un atributo estático se caracteriza :
para acceder a los atributos y/o funciones miembros. – Todos los objetos comparten este atributo
– Sólo se inicializa una vez (aunque se creen N objetos)
● Principalmente se utiliza en dos casos:
– Puede ser accedido por todos los objetos
– Cuando una función miembro con parámetros contienen nombres
similares de atributos que de parámetros. ● Para conseguir este objetivo se tiene que declarar el atributo
– Cuando se retorna el propio objeto como estático, usando la palabra reservada static
Programación II 47 Programación II 48
13. Atributos estáticos II Métodos constantes
● Ejemplo: Reflejar en la clase el número de objetos que hay. ● Un método constante es aquel que garantiza que ningún
atributo de la clase va a ser modificado por una función
Class Punto {
miembro. Para ello se utiliza la palabra reservada const.
static int cuantos; //Atributo compartido
● Casos:
public: – Función miembro constante. Se debe añadir la palabra reservada
detrás de los argumentos. Por ejemplo en funciones miembros que
Punto() {cuantos++;} //Incremento cuando se crea
hagan listado.
~Punto() {cuantos --;} //Decremento cuando se destruye
void mostrar () const;
.....
– Objetos constantes: Objetos que no se pueden modificar su estado.
}; Sólo podrán recibir mensajes constantes.
int Punto::cuantos=0; Importante: Se inicializa fuera de la clase const Punto p();
y no en los constructores, pues si no se – Objetos argumentos constantes: Para garantizar que dentro del objeto
inicializaría constantemente. no se va a modificar. Ej: Argumentos por referencia constantes.
Programación II 49 Programación II 50
Composición de clases Composición de Clases II
● Los atributos de una clase pueden ser tipos de datos simples, ● Cuando se crea un objeto se invocan automáticamente a los
tipos de datos definidos u otras clases. constructores de los objetos miembros:
– Antes que el constructor de la clase global
● Composición: Crear nuevas clases a partir de clases ya
– Según el orden en el que se declaren
existentes que actúan como atributos de la nueva clase.
● Esta nueva característica permite la creación de código a
class Punto {
partir de uno ya existente --> Reutilización.
.....
● La relación de composición generalmente se representa con };
la frase “tiene un”. class Linea {
● Ejemplo: Clase Línea se encuentra formada por dos puntos. private:
Punto _origen, _destino; //La clase linea tiene dos puntos. Punto p[2];
Linea Punto public:
tiene un
Linea();
Linea(const Punto& p1, const Punto& p2);
Linea(const Linea& l);
Linea& operator= (const Linea& l)
Programación II 51 Programación II 52
}
14. Bibliografía Recomendada Ejemplo: Clase punto
using namespace std; Punto::Punto() {
● Libros: cout << "Estoy en el constructor Defecto"<< endl;
#include <iostream> _x=0; _y=0; }
– Programación orientada a objetos. Roberto Rodríguez, Encarna Sosa Punto::Punto(int x, int y) {
cout << "Estoy en el constructor Parametrizado"<< endl;
y Alvaro Prieto. S004.421rodpro class Punto { _x=x; _y=y; }
Punto::Punto (const Punto& origen) {
– Programación en C++. Luis Joyanes. S004.43c++joy private: cout << “Constructor copia” << endl;
this->_x=origen._x; // dar_x(origen._x);
– Como programar en C++ . H. M. Deitel. S004.43C++dei int _x, _y; //Atributos this->_y=origen._y; // }
public: void Punto::dar_x (int x) {
– Resolución de problemas con C++. Savitch.S004.43C++sav this->_x=x; }
Punto(); //Constructor por defecto void Punto::dar_y (int y) {
this->_y=y; }
– El lenguaje de programación C++. Stroustrup, B. S004.43C++str Punto (int x, int y); //Constructor parametrizado Punto& Punto::operator= (const Punto & p) {
cout << “Operador asignación” << endl;
– Aprendiendo C++ para linux en 21 días. Jesse Liberty y David B. Punto (const Punto& origen); //Constructor Copia
this->_x=p._x;this->_y=p._y; return *this; }
Horvath. int leer_x() {return _x;} //Función miembro insertada Punto::~Punto() {
cout<<"Estoy en el destructor"<<endl; }
int leer_y() {return _y;} //Función miembro insertada
void dar_x(int x);
void dar_y(int y);
Punto& operator= (const Punto & p);
~Punto();
};
Programación II 53 Programación II 54
Ejemplo Clase Punto II Ejemplo de Composición. Linea
#ifndef linea_h // Evitar inclusiones múltiples #include "linea.hpp"
Ejemplo1 Ejemplo2 #include <iostream>
#define linea_h Linea::Linea(){
int main(){ int main(){ cout << "Constructor linea por defecto" << endl; }
#include "punto.hpp"
Punto p; //Defecto int m; class Linea { Linea::Linea (int x1,int y1, int x2, int y2):_origen(x1,y1),_destino(x2,y2){
Punto p1(5,4); //Parametrizado cout << "Constructor linea coordenadas" << endl; }
Punto * p[2]; private:
Punto p2(3,4); //Parametrizado
Punto p4[6]; //Defecto. 6 constructor p[0]= new Punto(4,4); //Cualquier otro constructor Linea::Linea (const Punto &O, const Punto &D):_origen(O), _destino(D){
Punto _origen, _destino; cout << "Constructor linea punto" << endl; }
Punto p5=p2; //Copia
Punto p6(p1); //Copia p[0]->leer_x(); public:
p1=p2; //Asignación Linea::Linea (const Linea& l):_origen(l._origen),_destino(l._destino){
cout<<"La coordenada X es: "<< p[0]->leer_x()<<endl; Linea(); //Constructor por defecto cout << "Constructor linea copia" << endl;
return 1;
} cout<<"La coordenada Y es: "<< p[0]->leer_y()<<endl; /* _origen=l._origen; //Otra forma de hacerlo
Linea (const Punto &O, const Punto &D); _destino=l._destino;*/ }
delete p[0]; Linea (int x1,int y1, int x2, int y2);
Punto& Linea::leer_origen(){
Punto * p1; Linea (const Linea& l); //Constructor Copia return (this->_origen); }
Punto& Linea::leer_destino() {
p1=new Punto[2]; //Se esta llamando al constructor por defecto
Punto& leer_origen(); Punto& leer_destino(); return (this->_destino); }
p1[0].leer_x(); void Linea::dar_origen(const Punto &O){
void dar_origen(const Punto &O); _origen=O; }
cout<<"La coordenada X es: "<< p1[0].leer_x()<<endl; void Linea::dar_destino(const Punto &D) {
void dar_destino(const Punto &D);
_destino=D; }
cout<<"La coordenada Y es: "<< p1[0].leer_y()<<endl; void Linea::mostrar() {
void mostrar();
delete []p1; _origen.mostrar();
Linea& operator= (const Linea & l); _destino.mostrar(); }
cin >> m; Linea& Linea::operator= (const Linea & l){
~Linea(); cout << "Operador asignación linea" << endl;
return 0; this->_origen=l._origen;this->_destino=l._destino; return *this; }
};
Linea::~Linea() {
}
Programación II 55 #endif
Programación II cout << "Destructor linea"<< endl; 56
}
15. Ejemplo de Composición. Linea II Ejercicios
#include <iostream.h> ● Implementar y desarrollar un programa principal para las
#include "punto.hpp" siguientes clases. Se debe definir todos sus constructores,
#include "linea.hpp"
operador =, destructor, mostrar, acceso y retorno a sus atributos.
int main(){
– Hora formado por tres enteros: horas, minutos, segundos. Funcionales
int m;
adicionales: suma dos objetos horas, una hora más grande que otra.
Punto p1(4,4), p2(5,5);
Linea L(4,4,5,5);
– Fecha formado por día, mes y año. Funciones adicionales: Sumar, restar
Linea L2(L);
dos fechas, calcular el tiempo transcurrido desde el año 1900.
L2.mostrar(); – Cadena formado por un atributo dinámico (cadena) y su longitud.
Linea *L3= new Linea (5,5,6,6); Funciones: longitud, acceso a una determinada posición, visualizar,
L3->mostrar(); primera posición de un carácter en un objeto cadena.
*L3=L2; //Cuidado: No L3=&L2 – Persona formado por los atributos: nombre (dinámico), edad, telefono
L3->mostrar(); (dinámico).
delete L3; – Entero formado por un valor entero. Funciones adicionales: suma, resta,
L2.mostrar(); multiplicación y división.
L.mostrar();
– Complejo formado por dos valores reales. Funciones adicionales: suma,
cin >> m;
resta, multiplicación y división.
return 0;
Programación II 57 Programación II 58
}
Ejercicios
● Composición
– Implementar la clase Rectángulo a partir de la clase Línea
– Implementar la clase Rectángulo a partir de la clase Punto
– Implementar de nuevo la clase persona formado por las siguientes
clases:
● Nombre: Clase Cadena
● Fecha Nacimiento: Clase Fecha
● Edad: Clase Entero
– Definir una clase que almacene información de un vehículo formado
por las siguientes clases:
● Marca: Clase Cadena
● Num_Puertas: Clase entero
● Potencia: Clase entero
Programación II 59