Ejercicio 1. Ejercicio 2

Documentos relacionados
Clases y Objetos en C++

Unidad V. Ya veremos qué poner en "algunas_palabras" y "algo_más", por ahora sigamos un poco más.

Informática PRÀCTICA 9 Curs Práctica Nº 9: Rango y precisión de representación de números en el ordenador.

Funciones Definición de función

Tema 6: Memoria dinámica

Tipos Recursivos de Datos

ESTRUCTURA DE DATOS. Memoria estática Memoria dinámica Tipo puntero Declaración de punteros Gestión de memoria dinámica Resumen ejemplo

Memoria Dinámica. Jornadas de Marzo 2010 Grupo de Usuarios de Linux Tania Pérez

Programación Orientada a Objetos en C++

Principios de Computadoras II

Programación orientada a objetos I

Práctica 3. Paso de parámetros entre subrutinas. 3. Consideraciones sobre el paso de parámetros

Tema: Plantillas en C++.

2.2 Nombres, Ligado y Ámbito

INTRODUCCIÓN A LA POO EN C++

Tema 10: Tipos de datos definidos por el usuario

Elementos de un programa en C

Programación. Test Autoevaluación Tema 3

Punteros y Memoria Dinámica II

Apuntadores en C y C++

Tema: Clases y Objetos en C#. Parte II.

Tema 13: Apuntadores en C

UNIDAD 3 Modularidad

UNIVERSIDAD DE LOS ANDES NUCLEO UNIVERSITARIO RAFAEL RANGEL (NURR) DEPARTAMENTO DE FISICA Y MATEMATICA AREA COMPUTACION TRUJILLO EDO.

Programación Orientada a Objetos. Resumen de Temas Unidad 3: Constructores y destructores

Tema 6: Clases. Índice

Variables y tipos básicos 1. Definir una variable de tipo char. Convertirla a una variable de tipo entera e imprimir su valor asociado.

Relación de prácticas de la asignatura METODOLOGÍA DE LA PROGRAMACIÓN Segundo Cuatrimestre Curso º Grado en Informática

Academia de computación de IE, ICA e ISISA. Unidad didáctica Programación Orientada a Objetos

Las plantillas permiten definir funciones genéricas.

Laboratorio de Arquitectura de Redes. Punteros en lenguaje C

Objetivo N 2. Conocer la Estructura General de un Programa en C++ Estructura de Datos Prof. Egilde Márquez

Algoritmo, Estructuras y Programación II Ing. Marglorie Colina

Tema: Sobrecarga. Objetivos. Materiales y Equipo. Introducción Teórica. Programación II. Guía No. 7

PROGRAMACIÓN ORIENTADA A OBJETOS

Tema 6. Gestión dinámica de memoria

! Qué es la POO?! Un paradigma de programación. ! No hay paradigmas mejores ni peores! Todos tienen sus ventajas e inconvenientes

Tema: Punteros.Puntero this en C#.

Programación 1 Tema 3. Información, datos, operaciones y expresiones

Ejercicios de tratamiento de errores

PUNTEROS (APUNTADORES)

PUNTEROS (Apuntadores)

Tipos de Datos Estructurados

Tema 2: Clase y objetos en C++ Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

Ejercicios de C. 1. Estructura de un programa. Objetivos: Practicar con el editor - usar el editor emacs emacs nombre.c

Tema 1. Programación modular. Programación Avanzada Ingeniería Técnica en Informática de Gestión Jorge Badenas

Examen Junio- Grupo B Lunes 17 de Junio - Programación en C++ Pág. 1

Unidad IV. Este tipo de codificación nos es permitido gracias a la sobrecarga, la cual se aplica a métodos y constructores.

Soluciones. boolean pruebaiteraseriegeometrica () { Serie s= new SerieGeometrica (1, 2); return (s.iterator() instanceof IteraSerieGeometrica); }

Programación orientada a objetos II

4. Operadores Operador asignación

En un arreglo x de n elementos los elementos del arreglo son: El número de índices determina la dimensionalidad del arreglo.

Memoria en C++ Punteros - Referencias Clases Y ahora, a trabajar! Memoria Dinámica en C++

Análisis semántico. Análisis semántico. Índice (I)

TEMA 02 TIPOS, OPERADORES Y EXPRESIONES

La sintaxis básica para definir una clase es la que a continuación se muestra:

Escuela Politécnica Superior de Elche

Estructura de datos y Programación

TEMA 3:Programación con Clases y Objetos.

Programación I Funciones

C++ me gusta++ Dr. Arno Formella. formella Universidad de Vigo Departamento de Informática E Ourense

Cadenas de caracteres

Programación de Videojuegos Tema 15 Tipos de Dato I. 15. Tipos de Dato I

Introducción al lenguaje C

Implementación de las Clases Pila, Cola, Lista y Arbol

Programación en C. Algoritmo y Estructura de Datos. Ing. M. Laura López. Programación en C

Programación orientada a objetos

class identificador{ //Bloque de propiedades (datos miembro, atributos, propiedades) //Bloque de métodos (comportamientos) }

Tema 18: Memoria dinámica y su uso en C

Principal material bibliográfico utilizado

Punteros. Programación en C 1

Bloque II. Elementos del lenguaje de programación Java

Manual de referencia de C++ Parte IV Variables Punteros. Preparado por Prof. Luis A. Ortiz Ortiz

Introducción a Java. Dr. (c) Noé Alejandro Castro Sánchez

Punteros. Lenguaje C ANSI

TEMA 7: Ficheros. TEMA 7: Ficheros Concepto de fichero

Abelardo Pardo. Iria Estévez Ayres. Damaris Fuentes Lorenzo. Pablo Basanta Val. Pedro J. Muñoz Merino. Hugo A. Parada.

ESTRUCTURAS. Struct Identificador_ tipo_estructura { Tipo miembro_1; /*Declaración de los miembros*/

Modulo 11. Clases y Objetos en Java

Conversión entre Tipos

Descripción y Contenido del Curso. Programación C++ Capacity Academy.

Transcripción:

Todos los ejercicios incluyen una parte opcional de mayor dificultad, indicada con una serie de asteriscos en función del grado de dificultad. Ejercicio 1 Este ejercicio servirá para practicar la declaración de plantillas. A continuación se da una lista de descripciones de funciones y clases de plantillas, se pide escribir una declaración apropiada para las mismas y comprobar que éstas compilan. 1. Declarar una función que toma dos parámetros de plantilla distintos de los cuales uno es el tipo de retorno y el otro es argumento. 2. Declarar una clase que toma un parámetro de plantilla, el cual es una variable miembro (atributo) de la misma. 3. Declarar una clase que toma dos parámetros de plantilla, uno como argumento al constructor y otro como tipo de retorno de una función miembro (método) sin argumentos. 4. Declarar una clase de plantilla con un parámetro entero con un valor por defecto cualquiera y que sirva como el tamaño de un atributo array. 5. * Declarar una clase que tiene como amiga a una clase de plantilla distinta (con tantos parámetros como se desee). 6. ** Declarar una clase en la que uno de los parámetros es a su vez una clase de plantilla. Nota: Dado que se trata sólo de generar declaraciones, y no escribir los cuerpos de las funciones, no hace falta que nuestro fichero.cpp tenga main. Para que el compilar no proteste usar la opción -c: g++ -c mi_fichero.cpp Así se compilará el fichero aunque no haya main, pero no se genera ningún programa, sólo un fichero objecto (que por defecto se llama igual pero con la extensión.o) Ejercicio 2 El objetivo de este ejercicio es declarar una función de plantilla sencilla y ver algunas de sus posibilidades. Se pide escribir una función menor que tome dos argumentos genéricos y use el operador < para devolver el menor de ellos como valor de retorno. La función debe ser capaz de dar este tipo de resultados: menor(2, 3) == 2 menor(6.0, 4.0) == 4.0 A continuación: 1. Comprobar su funcionamiento para parejas de argumentos numéricos del mismo tipo (int, double, float). 2. Comprobar que pasa si los argumentos son de distinto tipo (la respuesta dependerá de si se usó un parámetro de plantilla o dos para la declaración de la función, probar ambas posibilidades). 3. Declarar un clase (por ejemplo Fecha) que defina el operador < y verificar el

funcionamiento de la función. 4. La STL de C++ define un par de plantillas cuyo objetivo es similar al de la función menor. Se trata de las funciones std::min y std::max incluidas en la cabecera <algorithm>. Reemplazar la función menor por std::min en el código de prueba escrito en los apartados anteriores y probar que funciona. 5. * Intentar usar la función con literales de cadena y con objetos de la clase std::string (no combinados). Cuál es el único que funciona y por qué? (Nota: sólo uno de los casos funciona correctamente, el otro puede dar la impresión de que lo hace, pero se tratará de una mera coincidencia, hay que hacer pruebas con varias cadenas de cada clase para darse cuenta de cual no funciona) 6. ** Cómo se haría para que el código de prueba del ejercicio anterior también funcionase con el tipo de cadena para el que no lo hace? Pista: Las funciones de plantilla se pueden sobrecargar igual que las normales. Ejercicio 3 A veces resulta conveniente devolver una pareja de valores como valor de retorno de una función, evitando así tener que ensuciar la declaración de parámetros añadiendo dos parámetros pasados por referencia o puntero. La solución inmediata es declarar un struct que pueda albergar los tipos a devolver y usarlo como valor de retorno. Sin embargo, eso requiere declarar una estructura diferente para cada combinación de dos tipos que necesitemos, lo que resulta tedioso. Una solución simple la proporcionan las plantillas. 1. Declarar un struct de plantilla, Par, que toma dos parámetros. Cada parámetro será el tipo de un atributo de dicha clase. Asimismo la clase deberá proporcionar un constructor que tome una variable de cada tipo y un constructor sin argumentos. Escribir varias funciones que tomen dos argumentos (sin plantillas) y que devuelvan el tipo Par compuesto con esos argumentos. Componer las funciones para devolver parejas en las que alguno de los componentes es también un tipo Par. 2. La declaración de variables del tipo anterior es un poco prolija ya que siempre sólo se puede llamar al constructor si se hace una instanciación explícita, es decir, no se pueden deducir los parámetros. Por ejemplo Par(2, hola ) no compilaría, debería ser Par<int, const char *>(2, hola ) En el ejercicio anterior se han declarado funciones que toman pares y devuelven Par(es). Ahora se trata de escribir una función de plantilla que haga esto mismo exactamente, así para crear un par sólo habría que hacer: crear_par(2, hola ). Reemplazar las funciones compuestas Cual es el mecanismo por el cual el compilador sí puede determinar cual es el tipo que tiene que devolver esa función? 3. La STL proporciona la clase y función anterior, se trata de la plantilla pair y la función make_pair, de la cabecera <utility>. Estas clase es importante porque aparece en la interfaz de algunos contenedores estándar. Se trata pues de reemplazar el código de prueba de los ejercicios anteriores por estas utilidades.

4. ** Declarar una sobrecarga de plantilla del operador== a nivel global. Esta sobrecarga debe aceptar un párametro de tipo Par y otro de tipo pair (cada uno con sus parámetros) y compararlos. Escribir distintas pruebas en las que se verifique que expresiones de este estilo: make_pair(3, bool) == crear_par(3, bool) make_pair(crear_par('a', std::string( hola )), 10) == crear_par(make_pair('a', std::string( hola )), 10) crear_par(10, 45.0)!= make_pair(false, 'a') compilan y dan el resultado esperado. Pista: No basta con una sobrecarga sólo, hace falta poder comparar churras con merinas y merinas con churras. Ejercicio 4 El objetivo de este ejercicio es crear una clase de plantilla Vector que facilite el manejo de arrays y los dote de seguridad en el acceso a índices fuera de rango. La clase Vector a implementar recibirá un único parámetro de plantilla para el tipo a almacenar. Las funciones a implementar serán: 1. El contructor. Inicializa los atributos a valores seguros 2. Un metodo redimensionar. Cambia el tamaño máximo del vector, reserva espacio cuando sea necesario (por ej, primera reserva de memoria) y copia los datos del array viejo cuando sea necesario (por ej, redimensionar a un tamaño mayor). 3. El destructor, que liberará la memoria. 4. Operador [] para acceder a un elemento. Debe devolver el valor por referencia para que el siguiente código sea válido: Vector<int> v; v.redimensionar(1); v[0] = 10; // Modificación std::cout << v[0] << std::endl; //Acceso. Si se intenta acceder a un elemento por encima del máximo se debe imprimir un mensaje de error. Como ahora mismo no tenemos más recursos, a continuación se hará lo que se ha pedido, que con toda seguridad acabará en un acceso inválido a memoria. Nota: Un diseño más correcto incluiría una sobrecarga adicional del operador[] con modificadores const. 5. * No hemos definido constructor de copia. Qué peligros tendría asignar un Vector a otro? 6. * Definir el constructor de copia para que no haya peligro alguno (Pista: por simplicidad, el array interno no puede ser compartido, debe copiarse) 7. ** Un contructor de copia desde otro tipo de vector distinto que funcione cuando existe una conversión valida entre ambos tipos. Preocuparse sólo de los tipos escalares (int, float, double) porque entre ellos sí hay conversión. Nota: como se verá en las siguientes clases en detalle ya existe una clase, std::vector, que implementa este tipo de funcionalidades y muchas más. Ejercicio 5 En este ejercicio se va a escribir una clase de plantilla que haga de puntero inteligente. Un puntero inteligente debería ser una clase que tuviese prácticamente la misma sintaxis que un puntero normal, pero añada un manejo automático de la memoria para evitar problemas. En una primera

versión nuestra clase Puntero debería permitir código de este estilo: // crear un puntero con valor inicial nulo. Puntero<int> p1; // crear un puntero inicializado con un puntero. Puntero<int> p2 = new int(10); // asignar un puntero a un puntero nulo, tomar posesión del puntero p1 = new int(77); // asignar un puntero nuevo a un puntero con valor previo, // la memoria previa se libera y se toma posesión de la nueva p2 = new int(45); // asignación entre punteros inteligentes, el puntero destino libera cualquier memoria que pudiera poseer, toma la posesión del puntero origen y lo deja a nulo. // Dereferenciación del puntero std::cout << *p1 << ' ' << *p2 << std::endl; // Acceso a miembros para punteros a clases struct A { void f(); }; Puntero<A> p_a = new A; p_a->f(); // Al final del bloque se destruyen p1, p2 y pa, liberando la memoria a la que apuntan. Así lo que se exige al puntero inteligente sería lo siguiente: 1. Un constructor por defecto, uno de copia y un operador de asignación ( cuidado con la autoasignación!) 2. Un destructor 3. Que cuando se intente acceder a un puntero nulo se imprima un mensaje de error antes de que ocurra la catástrofe inminente (en código real en vez de imprimir un mensaje se usaría un assert o una excepción como se explicará en una lección posterior). 4. Una sobrecarga del operador* y del operador-> Escribir un programa que pruebe diversas cosas, se puede partir del ejemplo de arriba. Nuestro puntero anterior existe también ya en la STL, denominado auto_ptr y dentro de la cabecera <memory>. La característica más importante de este puntero es que es los punteros almacenados son exclusivos (al igual que en nuestro puntero) Cuestiones adicionales: 1. * Valdría la clase anterior como puntero inteligente para arrays? (Hay varias razones) 2. ** Sería posible escribir una clase sencilla que valiese para arrays y punteros normales? 3. *** Nuestro puntero es exclusivo. Sin embargo en la mayor parte de los casos interesa que cada variable puntero asignada desde un mismo puntero original apunte al mismo dato sin que ninguna pierda la referencia, ya que así es como funciona un puntero real. Una manera de llevar a cabo este propósito es llevar una cuenta del número de referencias al puntero y sólo liberarlo cuando esta llega a cero. En este apartado se trata de modificar nuestro puntero para incluir el contador de referencias (Pista: el contador de referencias tiene que ser compartido también por todas las variables que apuntan al mismo dato). Notas:

Un puntero de este estilo no es la solución definitiva a todos los problemas de manejo de memoria. Considerar que pasa por ejemplo si tenemos dos objetos con sendos punteros que se apuntan recíprocamente. Por desgracia, en la STL no existe ningún puntero que tenga esta funcionalidad. Para los curiosos, sí puede encontrar una clase shared_ptr como parte de Boost un conjunto de bibliotecas de C++ muy utilizados en todos los ámbitos.