Programación Avanzada en C++ L. Hernández
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
1
Programación Orientada a Objetos
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
2
Nuevas incorporaciones desde C Espacio de utilización de una variable:
se puede declarar variables en cualquier parte del programa. variables globales
Acceso a variables ocultas.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
3
Nuevas incorporaciones desde C Referencias
Nombre alternativo para una variable u objeto int i=1; int &x=i;
Las variables x e i se refieren al mismo espacio de memoria. Se tienen que inicializar siempre. Se utilizan en pase de parámetros a funciones donde se quiera modificar su contenido.
Memoria dinámica:
new tipo[tamaño]; delete [] puntero;
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
4
Nuevas incorporaciones desde C Declaraciones de funciones
Parámetros con valor por defecto. En funciones con varios parámetros:
• si el parámetro k-1 está definido por defecto, el parámetro k también tiene que estarlo.
Pase de parámetros por referencia.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
5
Nuevas incorporaciones desde C Operadores E/S:
operador extracción: >> operador inserción: << Stream de entrada estándar: cin Stream de salida estándar: cout
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
6
Evolución hacia la POO Objetivos de la evolución:
Menor interconexión entre las partes de un programa. Ocultación de la información. Abstracción: • que los componentes del S.W. sean lo más cercano posible a las ideas que componen el problema.
Re-utilización del código.
Todos estos objetivos están relacionados, pero la piedra angular es la ocultación de la información.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
7
Programación con procedimientos El programa se divide en dos partes:
Algoritmos Datos
La parte algorítmica se estructura en procedimientos. Beneficios:
Abstracción de operaciones. Extensión del lenguaje. Re-utilización del código.
Inconvenientes:
No existe una clara estructuración de los datos que los relacione con los procedimientos que los manejan. Indefensión ante varios problemas: • No se garantiza el correcto estado de las estructuras de información. • No hay independencia de representación.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
8
FIFO: Programación con procedimientos No hay nada que impida que un programador haga un mal uso de los datos.
Ejemplo: confundir el uso de cola y cabeza.
No es posible garantizar que la cola se encuentra en un estado correcto. ¿Que sucede si un día queremos cambiar la estructura de los datos?
Ejemplo: cambiar el vector de la cola por una lista enlazada. • Tendría que re-escribir el programa.
Realmente,¿qué parte del código es re-utilizable?.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
9
FIFO: Ocultación de la información Cierta parte de los datos y funciones sólo será accesible desde ciertas funciones. Si el interfaz está bien definido, el estado de la cola siempre es correcto. Si se cambia la estructura interna de los datos sólo hay que cambiar las funciones del interfaz. Re-utilización del código. Se aprovecha:
la estructura de datos las funciones que la manejan
Ocultación de la información = Encapsulamiento de los datos
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
10
Formas de ocultación de la información Módulos (Programación modular)
Las funciones (procedimientos) y datos se agrupan en diferentes ficheros (módulos). Para cada módulo se definen los procedimientos y datos que se exportan. Sólo se puede acceder desde fuera del módulo a aquella parte que ha sido exportada.
Objetos (Programación orientada a objetos)
Un módulo se compone de dos partes:
2008 © Luis Hernández
definición → Interfaz implementación → Código de la interfaz y de la parte oculta.
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
11
Programación modular Aportaciones de la modularidad
Descomposición de un problema complejo en módulos más simples. Re-utilización de los módulos existentes para desarrollar nuevo software. Independencia de la implementación. Ocultación de la información.
Limitaciones de la modularidad
Ejemplo: Sólo puedo tener una cola en mi programa.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
12
Programación orientada a objetos Los objetos son entidades que agrupan datos y procedimientos que operan sobre esos datos.
modulo ≈ fichero objeto ≈ variable
Los objetos se caracterizan por tres propiedades:
Estado Operaciones Identidad dentro del programa (=instanciación)
Una clase es la descripción de un conjunto de objetos similares. Los objetos son instancias de una clase.
Ejemplo: podemos definir la clase matriz y a partir de ella los objetos matriz1 y matriz2.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
13
Clases y objetos Clase:
Abstracción de un conjunto de objetos caracterizados por las mismas propiedades y los mismos comportamientos.
Objeto:
Abstracción capaz de responder a una petición del servicio de mensaje.
Un objeto es una instancia de una clase. La clase contiene su comportamiento y sus propiedades. El objeto puede crearse dinámicamente en el transcurso de la ejecución de un programa. 2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
14
Objetos
El mensaje es el único medio de comunicación entre los objetos.
Consiste en una petición explícita de una operación que debe realizar el objeto Puede ser asociado a una llamada de procedimiento
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
15
El concepto de objeto Objeto: Entidad de programación con componentes de dos tipos:
Estado: Datos Comportamiento: Procedimientos que manipulan los datos con exclusividad.
Cada objeto posee un interfaz que contiene los servicios que oferta al exterior.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
16
Programación orientada a objetos Acceso convencional vs OO Comunicación entre objetos:
Un objeto pide un servicio a otro por medio de un mensaje: destinatario + operación + argumentos
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
17
Globalidad vs Localidad Programación modular
Aquí los datos son globales, son accesibles desde todos los procedimientos.
Programación por objetos:
Aquí los datos son locales a cada objeto. Sólo son accesibles para los procedimientos (operaciones) definidos en el objeto.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
18
Clases y objetos Clase
vehiculo
Campos
velocidad nombre precio cantidad
Métodos
precioConIVA: devolver (1,16*precio) darVelocidad: devolver (velocidad) retirar(c): cantidad ← cantidad c añadir(c): cantidad ← cantidad + c
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
19
Declaración de clases Declaración de la clase Definición de las funciones de la clase Instanciación de la clase
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
20
Programa ejemplo: Pila
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
21
Programa ejemplo: Pila
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
22
Constructores y destructores Constructor
Función miembro de la clase que se ejecuta cuando se crea un objeto. Podemos tener varios constructores en una clase, pero han de diferir en los parámetros.
2008 © Luis Hernández
Destructor
Función miembro de la clase que se ejecuta al final de la vida de cada objeto.
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
23
Utilización de constructores
Utilización de constructores:
Sin parámetros: A a; Con un parámetro: A a(5); ó A a=5; Con varios parámetros: A a(5,3);
Constructores por defecto:
Constructor copia:
• Crea un objeto b2 donde los datos de b2 serán iguales a los de b1. • Aunque no se defina el constructor copia, éste existe para que se puedan pasar objetos como parámetros por valor.
Constructor sin parámetros:
• Aunque no se defina, éste existe para que se puedan definir objetos de la clase (no ejecuta nada).
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
24
Utilización de constructores Desaparición de constructores por defecto:
Constructor sin parámetros:
• Desaparece cuando definimos cualquier otro constructor.
Constructor copia:
• Desaparece cuando definimos un nuevo constructor copia. • Siempre hay un constructor copia, y solo uno, en cada clase.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
25
Constructor copia Definición Utilización
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
26
Clases compuestas
Una clase donde algún dato miembro es un objeto de otra clase. ¿Cuál es el orden de construcción? 2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
27
Expansión inline Evitar llamadas a funciones. El compilador simula el pase de parámetros.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
28
Clases y funciones friend Funciones friend:
Una función ajena a la clase pueda acceder a la parte privada de la clase.
Clases friend:
Todos los métodos de una clase puedan acceder a la parte privada de otra clase.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
29
Calificación de variables miembro Distinguir entre:
variables miembro de una clase otro tipo de variables.
Operador resolución de ámbito “::”
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
30
Palabra reservada this
Representa un puntero al objeto que recibe la llamada. Todos los objetos de todas las clases tienen this como dato miembro. 2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
31
Variables de clase e instancia Variables de clase:
común a todos los objetos (instancias) de una clase.
Variables de instancia:
propio de cada objeto (instancia) de la clase.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
32
Variables de clase e instancia
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
33
Funciones de clase Funciones de clase:
Actúan sobre variables de clase. Sólo pueden actuar sobre las variables de instancia de la propia clase cuando pertenecen a un objeto: • pasado como parámetro. • declarado dentro de la propia función.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
34
Punteros a objetos Declaración de punteros a objetos de una clase. Utilización del operador new y delete:
Al ejecutarse el operador new, se llama al constructor de la clase automáticamente (malloc no lo hace). delete llama al destructor (free no).
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
35
Ejemplo de vectores y punteros a objetos
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
36
Herencia
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
37
Herencia Definir una nueva clase:
como extensión de otra previamente definida. sin modificar la ya existente.
La nueva clase hereda de la clase anterior:
las variables. las operaciones .
Principal objetivo/ventaja:
Reutilización del código.
• Ahorro de esfuerzo. • Mayor confianza en el código.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
38
Organización jerárquica
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
39
Herencia en POO Una función recibe un objeto de la clase base. void Despedir (empleado);
Una función puede recibir objetos de la clase base y también de sus derivadas. empleado e; empleado_producción ep; empleado_comerciales ec; Despedir (e); Despedir (ep); Despedir (ec);
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
40
Herencia de métodos y variables Las clases derivadas reciben (=heredan) las variables y métodos de la clase base. Empleado_comercial ec; Empleado_produccion ep; ec.Cambiar_Sueldo(); ep.Cambiar_Sueldo();
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
41
Composición y herencia Composición:
Relación tener-un
Herencia:
Un coche tiene un motor
Contener un objeto.
2008 © Luis Hernández
Relación ser-un Un coche es un vehículo
Contener una clase.
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
42
Ejemplos de composición y herencia Clase persona y clase empleado.
Herencia: un empleado es una persona.
Clase persona y clase domicilio.
Composición: una persona tiene un domicilio.
Clase lista y clase nodo de la lista:
Composición: una lista tiene un puntero de tipo nodo al nodo que está en cabeza de la lista (tener-un).
Clase empresa, clase empleado y clase jefe de grupo de empleados.
Herencia entre empleado y jefe. • Un jefe es un empleado.
Composición entre empresa y empleado o jefe.
• Una empresa puede tener una lista de empleados y otra de jefes. • Por el principio de los subtipos, una empresa puede tener una única lista donde aparezcan tanto jefes como empleados.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
43
Ejemplo de herencia
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
44
Ejemplo de herencia Los miembros de la clase empleado se pueden utilizar en las clases derivadas tal y como si hubiesen sido definidos en éstas
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
45
Modos de acceso private
Lo que es “private” en la clase base no es accesible en la clase derivada.
public
Lo que definimos como “public” es accesible desde cualquier parte.
protected
Lo que definimos como “protected” en la clase base: • es accesible en la clases derivadas • no es accesible fuera de las clases derivadas o base.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
46
public
Tipos de herencia
los modos de acceso a los miembros de la clase base se quedan igual en la clase derivada.
protected
los miembros “public” de la clase base pasan a ser “protected”, el resto se queda igual.
private
todos los miembros de la clase base pasan a ser “private” en la derivada.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
47
Redefinición de miembros
A veces, interesa cambiar en la subclase la definición de algo que está en la clase base. Lo redefinido no desaparece. 2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
48
Ejemplo de redefinición de miembros
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
49
Herencia múltiple Una clase derivada hereda las características de más de una clase base.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
50
Constructores y destructores Construcción objeto clase derivada:
Primero se construye la parte heredada de la clase(s) base. • Se ejecutan los constructores de las clases base.
Por último se ejecuta el código del constructor de la clase derivada.
Destrucción objeto clase derivada:
El proceso es a la inversa que en la construcción.
• Se ejecuta primero el destructor de la clase derivada y a continuación los de las clases base.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
51
Ejemplo de constructores y destructores Constructores y destructores en la herencia
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
52
Ejemplo de constructores y destructores Constructores y destructores en clases compuestas y derivadas.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
53
Ejemplo de constructores y destructores Llamadas a los constructores de las clases base.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
54
Ejemplo de constructores y destructores
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
55
Ejemplo de constructores y destructores
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
56
Clase base virtual
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
57
Herencia virtual Si una clase base virtual define constructores, debe proporcionar uno de estos dos constructores:
un constructor sin parámetros un constructor que admita valores por defecto para todos los parámetros.
Las clases derivadas de una clase base virtual tienen que ser definidas como herencia virtual.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
58
Ejemplo de Herencia virtual
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
59
Punteros a clases derivadas
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
60
Polimorfismo
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
61
Polimorfismo El polimorfismo se refiere al hecho de que una misma función adopte múltiples formas. Esto se consigue por medio de la sobrecarga:
Sobrecarga de funciones:
• un mismo nombre de función para distintas funciones.
a = Sumar(c,d); a = Sumar(c);
Sobrecarga de operadores:
• un mismo operador con distintas funcionalidades. • Ejemplo: Sobrecargar el operador + sobre la clase cadena para que permita concatenar dos de estos objetos: entero1 = entero2 + 5; cadena1 = cadena2 + cadena3;
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
62
Sobrecarga de constructores Solo en caso de que no definamos ningún constructor, tenemos el constructor por defecto.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
63
Sobrecarga de funciones
Tenemos 2 funciones costructor string(). Tenemos 4 posibles llamadas a 4 funciones diferentes strcmp():
3 en la clase. 1 en la librería “string.h” de C.
Tenemos 2 funciones strcpy() en la clase.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
64
Sobrecarga de funciones En la sobrecarga de funciones se desarrollan distintas funciones con un mismo nombre pero distinto código. Las funciones que comparten un mismo nombre deben tener una relación en cuanto a su funcionalidad. Aunque comparten el mismo nombre, deben tener distintos parámetros de manera que el compilador pueda distinguir entre las distintas funciones cuando encuentra una llamada. Éstos pueden diferir en :
número tipo orden
El tipo del valor de retorno de una función no es válido como distinción.
Esto es debido a que ese valor en C++ no es necesario que sea recogido por otro objeto.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
65
Ejemplo de sobrecarga de funciones
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
66
Sobrecarga de operadores Consiste en definir nuevas funcionalidades para los operadores definidos en el lenguaje. Se pueden sobrecargar prácticamente todos los operadores del lenguaje:
No podemos inventar nuevos operadores. No podemos re-definir funcionalidades de los operadores que ya están definidas
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
67
Sobrecarga de operadores Al menos uno de los operandos del operador sobrecargado debe ser una clase definida por nosotros La sobrecarga de operadores es un caso particular de la sobrecarga de funciones:
el operando de la izquierda puede pasar a ser el propietario de la función, o bien el primer argumento de la función.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
68
Sobrecarga de operadores
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
69
Sobrecarga de operadores Para cualquier clase que se defina, el compilador define el operador asignación “=“. Cuando no me sirve, debo re-definirlo.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
70
Operador incremento y decremento Tiene dos posibles notaciones:
prefija: ++a postfija: a++
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
71
Operador subíndice Devolución de una referencia:
Se debe devolver una referencia cuando queremos que se pueda modificar el propio objeto que se devuelve.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
72
Operador subíndice Ejemplo de utilización de índices dobles.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
73
Conversión de clases Un constructor de Y que reciba X permite al compilador convertir objetos de la clase X en objetos de la clase Y.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
74
Operadores de conversión Los constructores de una clase X:
permiten definir qué otras clases pueden ser convertidas en la clase X.
Los operadores de conversión que se definen en una clase X:
permiten definir en qué otras clases se pueden convertir la clase x.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
75
Operadores de conversión
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
76
Ligadura dinámica Funciones virtuales:
Son una clase de sobrecarga de funciones, pero con la diferencia de: • Sobrecarga de funciones: se decide que función se va a ejecutar en tiempo de compilación. • Funciones virtuales: se decide en tiempo de ejecución (poliformismo en tiempo de ejecución).
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
77
Ligadura dinámica
Se ejecutará la función muestra() de alumno o de profesor dependiendo de la clase de objeto a la que apunte p (ligadura dinámica, en tiempo de ejecución). La función persona::muestra() no se ejecuta porque es virtual y ha sido substituida en cada clase derivada. Si no se hubiera definido como virtual la función muestra() en la clase persona se ejecutaría siempre persona::muestra() 2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
78
Funciones virtuales Cuando se define una función virtual:
El prototipo debe ser el mismo en las clases base y derivadas.
Una función definida como virtual en una clase base:
es virtual en todas sus clases derivadas, sea cual sea el nivel de derivación. Puede ser re-definida o no en las clases derivada.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
79
Clases abstractas No tiene mucho sentido:
definir código a la función figura:area() existan objetos de la clase figura
Solución: Podemos definir la clase figura como una clase abstracta.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
80
Clases abstractas Funciones virtuales puras:
Las clases derivadas están obligadas a re-definirla.
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
81
Destructor virtual
2008 © Luis Hernández
Programación en Ingeniería Electrónica | Programacion Avanzada en C++
82