POO con C++

download POO con C++

of 174

Transcript of POO con C++

  • 8/10/2019 POO con C++

    1/174

  • 8/10/2019 POO con C++

    2/174

  • 8/10/2019 POO con C++

    3/174

    libropoo 2011/2/19 19:02 page 1 #1

    Prlogo

    Desde principio de la dcada de los noventa hasta la actualidad, la Progra-macin Orientada a Objetos se ha establecido como el paradigma ms exten-dido entre la comunidad de programadores. Las asignaturas de programacinde las Facultades y Escuelas de Informtica no han sido ajenas al uso de esteparadigma de programacin. Estas asignaturas, normalmente, se han basadoen buenos y completos libros de expertos en la materia. No en vano, existe unaamplia literatura acerca del tema. Pero quizs, esta amplia literatura provoca,que, tanto profesores como alumnos, o incluso, personas externas al mbitoacadmico interesadas en este paradigma, se vean desbordados ante la canti-dad de material disponible, del cual, adems, posiblemente necesiten slo unapequea parte.

    La intencin de los autores al escribir este libro es la de cubrir una laguna

    que, en nuestra opinin, existe en la vasta literatura acerca del tema: la falta deuna gua accesible y concisa de introduccin a los conceptos ms importantesde la Programacin Orientada a Objetos. Por tanto, este libro surge con elobjetivo de presentar los conceptos ms importantes del paradigma de unamanera sencilla y agradable al lector, apoyando los conceptos presentados conejemplos que ayuden a la comprensin de todo lo expuesto.

    Este libro se encuentra dividido en los siguientes ocho captulos.En el primer captulo se contextualiza la Programacin Orientada a Objetos

    dentro de la historia de la programacin.En el captulo segundo se definen los conceptos bsicos de clases y obje-

    tos junto con el principio bsico de la Programacin Orientada a Objetos: laencapsulacin.

    En el tercer captulo se explican los mecanismos bsicos de reutilizacin de

    cdigo: la composicin y la herencia.En el captulo cuatro se define el concepto de polimorfismo. As, se expli-

    ca el concepto de ligadura, las funciones virtuales, la sobrescritura, las clasesabstractas, los constructores, funciones virtuales, destructores, y la diferenciaentre sobrecarga y sobrescritura.

    En el quinto captulo se explica el manejo de errores de la programacintradicional y se compara con la foma de hacerlo en C++: manejo de excepcio-nes.

    1

  • 8/10/2019 POO con C++

    4/174

    libropoo 2011/2/19 19:02 page 2 #2

    En el sexto captulo se define el concepto de estructura de datos y comoejemplo, se presenta una de las estructuras de datos ms utilizadas: la estruc-tura rbol.

    Por su parte, en el captulo siete, se presenta una metodologa de identifi-cacin y modelado de clases de objetos.

    Como ltimo captulo, en el captulo ocho, se presentan otras caractersticasrelevantes de C++ que se salen del mbito de la programacin orientada aobjetos.

    Finalmente, en el apndice se pueden encontrar una relacin de los erroresms comunes, as como una batera de ejercicios para que el lector practique ycomprenda todos los conceptos expuestos en este libro.

    2

  • 8/10/2019 POO con C++

    5/174

    libropoo 2011/2/19 19:02 page 3 #3

    ndice general

    1. Introduccin 71.1. Paradigmas de Programacin: Evolucin . . . . . . . . . . . . . 7

    1.1.1. Programacin Estructurada . . . . . . . . . . . . . . . . 71.1.2. Programacin Orientada a Objetos: Caractersticas base 81.1.3. Programacin Orientada a Objetos: Historia . . . . . . 8

    1.2. Procesos de Desarrollo Software . . . . . . . . . . . . . . . . . . 111.3. El lenguaje C++ . . . . . . . . . . . . . . . . . . . . . . . . . . 12

    1.3.1. Lenguaje de ejemplo . . . . . . . . . . . . . . . . . . . . 131.4. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

    2. Clases y objetos 152.1. Concepto de clase y objeto . . . . . . . . . . . . . . . . . . . . 15

    2.1.1. Clases y objetos en C++ . . . . . . . . . . . . . . . . . 162.1.2. El operador this . . . . . . . . . . . . . . . . . . . . . . 17

    2.2. Encapsulacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2.1. Encapsulacin en C++. Modificadores de acceso . . . . 18

    2.3. Creacin y eliminacin de objetos . . . . . . . . . . . . . . . . 202.3.1. Constructores . . . . . . . . . . . . . . . . . . . . . . . 20

    2.3.1.1. Constructores en C++ . . . . . . . . . . . . . 212.3.1.2. Clasificacin de constructores . . . . . . . . . 23

    2.3.2. Destructores . . . . . . . . . . . . . . . . . . . . . . . . 242.3.2.1. Destructores en C++ . . . . . . . . . . . . . . 25

    2.3.3. Ejemplo de creacin y eliminacin de objetos . . . . . . 252.3.4. Creacin y eliminacin dinmica de objetos . . . . . . . 29

    2.4. Paso de objetos como parmetros a funciones . . . . . . . . . . 302.4.1. Paso de objetos por valor . . . . . . . . . . . . . . . . . 312.4.2. Paso de objetos por referencia . . . . . . . . . . . . . . 33

    2.5. Funciones que devuelven objetos . . . . . . . . . . . . . . . . . 352.5.1. Por referencia . . . . . . . . . . . . . . . . . . . . . . . 352.5.2. Por valor . . . . . . . . . . . . . . . . . . . . . . . . . . 37

    2.6. Miembros estticos . . . . . . . . . . . . . . . . . . . . . . . . 372.6.1. Atributos miembro estticos . . . . . . . . . . . . . . . 37

    3

  • 8/10/2019 POO con C++

    6/174

    libropoo 2011/2/19 19:02 page 4 #4

    NDICE GENERAL

    2.6.2. Funciones miembro estticas . . . . . . . . . . . . . . . 382.7. Sobrecarga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

    2.7.1. Funciones sobrecargadas . . . . . . . . . . . . . . . . . . 402.7.2. Operadores sobrecargados . . . . . . . . . . . . . . . . 40

    2.8. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

    3. Mecanismos de reutilizacin 453.1. Composicin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

    3.1.1. Problema . . . . . . . . . . . . . . . . . . . . . . . . . . 463.1.2. Concepto . . . . . . . . . . . . . . . . . . . . . . . . . . 483.1.3. La composicin en C++ . . . . . . . . . . . . . . . . . 48

    3.1.4. Interfaz de la clase contenedora . . . . . . . . . . . . . . 503.2. Herencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

    3.2.1. Problema . . . . . . . . . . . . . . . . . . . . . . . . . . 553.2.2. Concepto . . . . . . . . . . . . . . . . . . . . . . . . . . 553.2.3. Jerarquas de clases . . . . . . . . . . . . . . . . . . . . 563.2.4. La herencia en C++ . . . . . . . . . . . . . . . . . . . . 58

    3.2.4.1. Control de acceso a los miembros de la clase base 583.2.4.2. Mayor control de acceso a los miembros de la

    clase base . . . . . . . . . . . . . . . . . . . . . 633.2.4.3. Constructores y destructores en la herencia . 633.2.4.4. Redefinicin . . . . . . . . . . . . . . . . . . . 683.2.4.5. Conversiones entre objetos de la clase base y

    objetos de las clases derivadas . . . . . . . . . 703.2.4.6. Herencia mltiple . . . . . . . . . . . . . . . . 713.2.4.7. Sobrecarga y redefinicin . . . . . . . . . . . . 72

    3.3. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

    4. Polimorfismo 754.1. Concepto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 754.2. Polimorfismo en C++ . . . . . . . . . . . . . . . . . . . . . . . 76

    4.2.1. Ligadura . . . . . . . . . . . . . . . . . . . . . . . . . . 774.2.2. Funciones virtuales . . . . . . . . . . . . . . . . . . . . . 784.2.3. Sobrescritura . . . . . . . . . . . . . . . . . . . . . . . . 79

    4.2.3.1. Extensibilidad y estructuras polimrficas . . . 794.2.3.2. Mtodo virtual no sobrescrito . . . . . . . . . 80

    4.2.4. Clases abstractas . . . . . . . . . . . . . . . . . . . . . . 814.2.5. Constructores y funciones virtuales . . . . . . . . . . . 824.2.6. Destructores . . . . . . . . . . . . . . . . . . . . . . . . 84

    4.2.6.1. Destructor virtual . . . . . . . . . . . . . . . . 844.2.6.2. Destructor virtual puro . . . . . . . . . . . . . 864.2.6.3. Destructores y funciones virtuales . . . . . . . 86

    4.3. Sobrecarga y sobrescritura . . . . . . . . . . . . . . . . . . . . . 884.4. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

    4

  • 8/10/2019 POO con C++

    7/174

    libropoo 2011/2/19 19:02 page 5 #5

    NDICE GENERAL

    5. Excepciones 915.1. Concepto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 915.2. Manejo de errores tradicional . . . . . . . . . . . . . . . . . . . 915.3. Excepciones en C++ . . . . . . . . . . . . . . . . . . . . . . . 93

    5.3.1. Lanzar y capturar excepciones . . . . . . . . . . . . . . 935.3.2. Restriccin de excepciones permitidas . . . . . . . . . . 985.3.3. Relanzar excepciones . . . . . . . . . . . . . . . . . . . . 995.3.4. Excepciones definidas por el usuario . . . . . . . . . . . 1015.3.5. Excepciones en constructores y destructores . . . . . . 102

    5.4. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

    6. Estructuras de datos 1056.1. Concepto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1056.2. rboles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

    6.2.1. Representacin y recorrido de los rboles binarios . . . . 1076.2.2. rbol binario de bsqueda . . . . . . . . . . . . . . . . . 1086.2.3. rboles balanceados . . . . . . . . . . . . . . . . . . . . 1096.2.4. Algoritmos principales de un ABO . . . . . . . . . . . . 109

    6.2.4.1. Insercin de nodos . . . . . . . . . . . . . . . . 1096.2.4.2. Eliminacin de nodos . . . . . . . . . . . . . . 1106.2.4.3. Recorridos del rbol . . . . . . . . . . . . . . . 111

    6.2.5. Implementacin de un rbol binario ordenado . . . . . 1126.3. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

    7. Identificacin y modelado 1217.1. Identificacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

    7.1.1. Anlisis gramatical para bsqueda de clases . . . . . . 1227.1.2. Clasificacin de clases potenciales . . . . . . . . . . . . . 1247.1.3. Clases obtenidas . . . . . . . . . . . . . . . . . . . . . . 124

    7.2. Identificacin de atributos . . . . . . . . . . . . . . . . . . . . 1267.3. Identificacin de operaciones . . . . . . . . . . . . . . . . . . . 128

    7.3.1. Casos de Uso y Diagramas de Casos de Uso . . . . . . 1287.3.1.1. Diagrama de Casos de Uso de nuestro sistema 129

    7.3.2. Anlisis gramatical de verbos . . . . . . . . . . . . . . . 1307.3.3. Estudio de las acciones . . . . . . . . . . . . . . . . . . 1317.3.4. Operaciones obtenidas . . . . . . . . . . . . . . . . . . . 131

    7.4. Modelado del Diseo Esttico . . . . . . . . . . . . . . . . . . . 1347.4.1. Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1347.4.2. Relaciones . . . . . . . . . . . . . . . . . . . . . . . . . . 1367.4.3. Diagrama de Clases del Problema Propuesto . . . . . . 141

    7.5. Modelado de aspectos dinmicos . . . . . . . . . . . . . . . . . 1437.5.1. Bifurcaciones e iteraciones . . . . . . . . . . . . . . . . . 1457.5.2. Diagrama de Secuencias de una operacin del Problema

    Propuesto . . . . . . . . . . . . . . . . . . . . . . . . . 147

    5

  • 8/10/2019 POO con C++

    8/174

    libropoo 2011/2/19 19:02 page 6 #6

    NDICE GENERAL

    7.6. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

    8. Otras caractersticas de C++ 1518.1. Programacin genrica . . . . . . . . . . . . . . . . . . . . . . . 151

    8.1.1. Formato de plantilla de funcin . . . . . . . . . . . . . . 1518.1.2. Plantillas de clase . . . . . . . . . . . . . . . . . . . . . 153

    8.2. Biblioteca estndar . . . . . . . . . . . . . . . . . . . . . . . . 1568.2.1. Espacios de nombres . . . . . . . . . . . . . . . . . . . . 1578.2.2. El tipo string . . . . . . . . . . . . . . . . . . . . . . . . 1588.2.3. STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

    8.3. Funciones friend . . . . . . . . . . . . . . . . . . . . . . . . . . 161

    8.4. Funciones en lnea . . . . . . . . . . . . . . . . . . . . . . . . . 1628.5. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

    A. Errores y ejercicios 165A.1. Relacin de los errores ms comunes . . . . . . . . . . . . . . . 165A.2. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

    A.2.1. Clases y objetos . . . . . . . . . . . . . . . . . . . . . . 167A.2.2. Mecanismos de reutilizacin . . . . . . . . . . . . . . . . 168A.2.3. Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . 169A.2.4. Excepciones . . . . . . . . . . . . . . . . . . . . . . . . . 169A.2.5. Identificacin y modelado . . . . . . . . . . . . . . . . . 170

    6

  • 8/10/2019 POO con C++

    9/174

    libropoo 2011/2/19 19:02 page 7 #7

    Captulo 1

    Introduccin1.1. Paradigmas de Programacin: Evolucin

    El mundo del desarrollo de software est sometido a un proceso evoluti-vo constante. Actualmente, podemos ver cmo ha sufrido una gran evolucindesde el cdigo mquina y el ensamblador a travs de conceptos como la pro-gramacin procedural, la programacin estructurada, la programacin lgica,etctera hasta llegar a la programacin orientada a objetos, que es el paradigmams extendido hoy en da.

    1.1.1. Programacin Estructurada

    Como surgi en su da el paradigma de Programacin Estructurada paraintentar paliar las deficiencias de la programacin en ese momento, la Pro-gramacin Orientada a Objetos aparece como una evolucin natural en losparadigmas de programacin que busca solucionar los principales problemasdel paradigma anterior. Un breve resumen de las deficiencias que este nuevoparadigma intenta solventar sera el siguiente:

    Distinta abstraccin del mundo. La programacin clsica se centra enel comportamiento, normalmente representado por verbos, mientras quenuestra mente se centra en los seres, a los que, normalmente, identificamos

    con sustantivos.Dificultad en modificacin y actualizacin. Los programas suelen tenerdatos compartidos por varios subprogramas, esto puede provocar quecualquier ligera modificacin en un mdulo afecte indirectamente al resto.

    Dificultad en mantenimiento. Es complicado encontrar todos los erroresen grandes aplicaciones, lo que origina que muchos no aparezcan hastaestar la aplicacin en explotacin.

    7

  • 8/10/2019 POO con C++

    10/174

    libropoo 2011/2/19 19:02 page 8 #8

    CAPTULO 1. INTRODUCCIN

    Dificultad en reutilizacin. Normalmente las subrutinas son demasiadodependientes del contexto de un programa como para poder aprovecharlasen un nuevo programa.

    A la hora de afrontar la construccin de grandes aplicaciones, estos defectospueden provocar que muchos proyectos sean inabordables. La ProgramacinOrientada a Objetos surgi con el objetivo de erradicar los problemas expuestos.

    1.1.2. Programacin Orientada a Objetos: Caractersticasbase

    La Programacin Orientada a Objetos supone un cambio en la concepcindel mundo de desarrollo de software, introduciendo un mayor nivel de abstrac-cin que permite mejorar las caractersticas del cdigo final. De manera muybsica, las aportaciones de este paradigma se pueden resumir en:

    Conceptos de clase y objeto, que proporcionan una abstraccin del mundocentrada en los seres y no en los verbos.

    Los datos aparecen encapsulados dentro del concepto de clase. El ac-ceso a los datos se produce de manera controlada e independiente de larepresentacin final de los mismos. Como consecuencia, se facilita el man-tenimiento y la evolucin de los sistemas, al desaparecer las dependenciasentre distintas partes del sistema.

    Mediante conceptos como la composicin, herencia y polimorfismo se con-sigue simplificar el desarrollo de sistemas. La composicin y la herencianos permiten construir clases a partir de otras clases, aumentando en granmedida la reutilizacin.

    La razn histrica del origen de estas aportaciones se explica en el siguienteapartado.

    1.1.3. Programacin Orientada a Objetos: Historia

    Contrariamente a la creencia de mucha gente, la Programacin Orientada aObjetos (POO a partir de ahora) no es un tema nuevo de discusin. Es ciertoque en aos recientes la POO ha tomado nueva fuerza y ha renacido como

    un paradigma. Sin embargo fue a finales de los aos 60 cuando estas tcnicasfueron concebidas. Para entender su origen hay que situarse en el contextode la poca, en el que el desarrollo y mantenimiento de proyectos softwarepresentaban evidentes problemas de complejidad, coste y eficiencia. Uno de losgrandes problemas que surgan consista en la necesidad de adaptar el softwarea nuevos requisitos imposibles de haber sido planificados inicialmente. Este altogrado de planificacin y previsin es contrario a la propia realidad. El hombreaprende y crea a travs de la experimentacin. La Orientacin a Objetos brinda

    8

  • 8/10/2019 POO con C++

    11/174

    libropoo 2011/2/19 19:02 page 9 #9

    CAPTULO 1. INTRODUCCIN

    estos mtodos de experimentacin, no exige la planificacin de un proyecto porcompleto antes de escribir la primera lnea de cdigo.

    Esto mismo pensaron en 1967, Krinsten Nygaard y Ole-Johan Dahl de laUniversidad de Oslo, en el Centro Noruego de Computacin, donde se dedica-ban a desarrollar sistemas informticos que realizaban simulaciones de sistemasmecnicos, por ejemplo motores, para analizar su rendimiento. En este desa-rrollo se encontraban con dos dificultades, por un lado los programas eran muycomplejos y, por otro, forzosamente tenan que ser modificados constantemen-te. Este segundo punto era especialmente problemtico; ya que la razn deser de los programas era el cambio y no slo se requeran varias iteracionespara obtener un producto con el rendimiento deseado, sino que muchas veces

    se queran obtener diversas alternativas viables, cada una con sus ventajas einconvenientes.

    La solucin que idearon fue disear el programa paralelamente al objetofsico. Es decir, si el objeto fsico tena un nmero xde componentes, el pro-grama tambin tendraxmdulos, uno por cada pieza. Dividiendo el programade esta manera, haba una total correspondencia entre el sistema fsico y el sis-tema informtico. As, cada pieza fsica tena su abstraccin informtica en unmdulo. De la misma manera que los sistemas fsicos se comunican envindoseseales, los mdulos informticos se comunicaran envindose mensajes. Parallevar a la prctica estas ideas, crearon un lenguaje llamado Simula 67.

    Este enfoque resolvi los dos problemas planteados. Primero, ofreca unaforma natural de dividir un programa muy complejo y, en segundo lugar, el

    mantenimiento pasaba a ser controlable. El primer punto es obvio. Al dividirel programa en unidades informticas paralelas a las fsicas, la descomposicines automtica. El segundo punto tambin se resuelve. En cada iteracin desimulacin, el analista querr cambiar o bien piezas enteras o bien el compor-tamiento de alguna pieza. En ambos casos la localizacin de los cambios estperfectamente clara y su alcance se reduce a un componente, siempre y cuandola interfaz del mismo no cambie. Por ejemplo, si se estuviese simulando el motorde un coche, puede que se quisiera modificar el delco utilizado en la simulacinanterior. Si el nuevo delco tuviera la misma interfaz (mismas entradas y salidas)o se cambiase slo su comportamiento interno, nada del sistema (a parte deldelco) estara afectado por el cambio.

    Con Simula 67 se introducen por primera vez los conceptos de clases, obje-tos, herencia, procedimientos virtuales y referencias a objetos (conceptos muy

    similares a los lenguajes Orientados a Objetos de hoy en da). En esta poca,Algol 60 era el lenguaje de moda y Cobol el ms extendido en aplicaciones em-presariales, por lo que el nacimiento de Simula 67 y la Orientacin a Objetos enEuropa pas inadvertido para gran parte de los programadores. En la actuali-dad Simula 67 se conoce simplemente como Simula, y contrariamente a lo quepudiera pensarse, todava est en uso, mantenido por una pequea comunidadde programadores, en su mayora noruegos, y compiladores disponibles en lared.

    9

  • 8/10/2019 POO con C++

    12/174

    libropoo 2011/2/19 19:02 page 10 #10

    CAPTULO 1. INTRODUCCIN

    El siguiente paso se da en los aos 70 en los Estados Unidos, ms concre-tamente en el Centro de Investigacin de Palo Alto (PARC), California, dondeXerox tiene un centro de investigacin en el que los cientficos trabajan enconceptos que puedan convertirse en productos industriales al cabo de 10 a 20aos. En aquellos aos contrataron a un joven llamado Alan Kay, que vena dela Universidad de Utah, donde haba estado trabajando con grficos, y habaexaminado un nuevo compilador procedente de Noruega, llamado Simula. Kayencontr conceptos, que ms tarde aprovech en Xerox, para llevar a trminolas ideas que propona en su tesis doctoral. stas consistan bsicamente en lapropuesta de construccin de un ordenador llamado Dynabook, adecuado paraser utilizado por nios. El ordenador no tena teclado, la pantalla era sensible

    al tacto y la mayor parte de la comunicacin era grfica. Al desarrollar esteproyecto se inventaron el mouse y los entornos grficos. Al volver a encontrarseen Palo Alto con una programacin compleja y experimental, como en el casode Nygaard y Dahl, Kay, junto con Adele Goldberg y Daniel Ingalls, decidie-ron crear un lenguaje llamado SmallTalk. Este lenguaje de programacin esconsiderado el primer lenguaje Orientado a Objetos puro, dnde todo lo quese crea son clases y objetos, incluyendo las variables de tipos ms simples. Laprimera versin se conoci como Smalltalk-72, aunque fueron surgiendo nuevasversiones (76,80,..) que pasaron de ser desarrolladas slo para mquinas Xeroxa serlo para la mayora de plataformas disponibles.

    Hasta este momento, uno de los defectos ms graves de la programacinera que las variables eran visibles desde cualquier parte del cdigo y podan

    ser modificadas incluyendo la posibilidad de cambiar su contenido (no existenniveles de usuarios o de seguridad, o lo que se conoce como visibilidad). D.Parnas fue quien propuso la disciplina de ocultar la informacin. Su idea eraencapsular cada una de las variables globales de la aplicacin en un slo mdulo

    junto con sus operaciones asociadas, de forma que slo se poda tener acceso aestas variables a travs de sus operaciones asociadas. El resto de los mdulos(objetos) podan acceder a las variables slo de forma indirecta mediante lasoperaciones diseadas para tal efecto.

    En los aos ochenta surgen nuevos lenguajes orientados a objetos basadosen Lisp. Esto se debe principalmente a que este lenguaje dispona de meca-nismos que permitan la implementacin basndose en orientacin a objetos.Entre los lenguajes surgidos de Lisp podemos destacar Flavors, desarrolladoen el MIT, Ceyx, desarrollado en el INRIA, y Loops, desarrollado por Xerox.

    Este ltimo introdujo el concepto de la programacin orientada a datos con laque se puede enlazar un elemento de datos con una rutina y que dio paso ala programacin controlada por eventos. La mayora de las vertientes tomadaspor estos lenguajes se fusionaron en CLOS (Common Lisp Object System) quefue el primer lenguaje orientado a objetos que tuvo un estndar ANSI. En 1984,Bjarne Stroustrup de ATT-Bell se plante crear un sucesor al lenguaje C, e in-corpor las principales ideas de Smalltalk y de Simula 67, creando el lenguajeC++, quizs el lenguaje responsable de la gran extensin de los conceptos de

    10

  • 8/10/2019 POO con C++

    13/174

    libropoo 2011/2/19 19:02 page 11 #11

    CAPTULO 1. INTRODUCCIN

    la orientacin a objetos. Posteriores mejoras en herramientas y lanzamientoscomerciales de C++ por distintos fabricantes, justificaron la mayor atencinhacia la programacin Orientada a Objetos en la comunidad de desarrollo desoftware. El desarrollo tcnico del hardware y su disminucin del costo fue eldetonante final. En esta misma dcada se desarrollaron otros lenguajes Orien-tados a Objetos como Objective C, Object Pascal, Ada y otros.

    En el inicio de los aos 90 se consolida la Orientacin a Objetos como unade las mejores maneras para resolver problemas de programacin. Aumenta lanecesidad de generar prototipos ms rpidamente (concepto RAD Rapid Apli-cation Development) sin esperar a que los requisitos iniciales estn totalmenteprecisos. En esta dcada se implanta con fuerza el concepto de reutilizacin,

    cuyo sentido es facilitar la adaptacin de objetos ya creados a otros usos di-ferentes a los originales sin necesidad de modificar el cdigo ya existente. Amedio y largo plazo, el beneficio que puede obtenerse derivado de la reutiliza-cin es muy importante, y, quizs, es la razn principal por la que la industriainformtica se ha abocado a la orientacin a objetos. Avanzando algunas cifras,se puede indicar que los niveles de reutilizacin de software pasan del 5-15 % encentros no orientados a objetos, a niveles por encima del 80 % en los orientadosa objetos.

    Con la reutilizacin como pilar bsico de su filosofa, un equipo de SunMicrosystems crea Java en 1995, con el objetivo de conquistar el mundo de laprogramacin, teniendo gran xito en aplicaciones en red. No en vano, captmucha atencin en los primeros meses de 1996 en base a ser considerado el

    medio para dominar Internet. Java es totalmente orientado a objetos. Estbasado en C++, intentando evitar los principales problemas del mismo, como,por ejemplo, el acceso directo a memoria dinmica. Se fundamenta en el uso debytecode (cdigo de bajo nivel, portable e interpretable) y una mquina virtualaccesible para todo el mundo que ejecuta esos bytecodes. Hoy en da es lo mscercano a lo que podra denominarse una mquina universal.

    El mundo de los lenguajes de programacin orientados a objeto evolucio-na da a da y, continuamente, surgen nuevos lenguajes o nuevas versiones delenguajes ya consolidados.

    1.2. Procesos de Desarrollo Software

    Evidentemente, el desarrollo de un sistema software debe seguir un procesoque especifique cmo debe ser, que permita controlar y seguir la evolucin delsistema y que permita establecer aproximadamente su coste. El estudio de lascaractersticas de estos procesos se lleva a cabo en el mbito de la comunidadde Ingeniera del Software.

    Bsicamente, podemos hablar de dos tipos procesos:

    En cascada.

    11

  • 8/10/2019 POO con C++

    14/174

    libropoo 2011/2/19 19:02 page 12 #12

    CAPTULO 1. INTRODUCCIN

    Iterativo (o incremental).

    La diferencia fundamental entre ellos consiste en la forma de dividir un proyectoen partes ms pequeas.

    Los procesos en cascada dividen un proyecto segn las actividades. La cons-truccin de un sistema software conlleva una serie de actividades que componenel ciclo de vida software: anlisis de requisitos, diseo, implementacin y prue-bas. De esta manera, los procesos en cascada dividirn un proyecto de 1 ao deduracin en, por ejemplo, una fase de anlisis de 2 meses, una fase de diseo de4 meses, una fase de implementacin de 3 meses y una de prueba de 3 meses.

    Por su parte, los procesos iterativos dividen un proyecto en subconjuntos de

    funcionalidad. De esta forma, un proyecto de 1 ao se dividira en 3 iteracionesde 4 meses. En la primera iteracin, se realizara todo el ciclo de vida softwarepara la cuarta parte de los requisitos. El resultado de la primera iteracin seraun sistema software con la cuarta parte de la funcionalidad. En las siguientesiteraciones se continuara evolucionando ese sistema, introduciendo el resto defuncionalidad.

    Dentro de la comunidad orientada a objetos, se suele optar por procesositerativos que responden mejor al problema derivado de los cambios en losrequisitos. En muchos campos de aplicacin, los requisitos van cambiando alo largo del desarrollo del sistema. Por lo tanto, los procesos en cascada semuestran menos efectivos; ya que, su flexibilidad ante estos cambios es muchomenor.

    1.3. El lenguaje C++

    Como ya vimos anteriormente, C++ nace a mediados de los ochenta de lamano de Bjarne Strouptup. En las primeras versiones era un simple preproce-sador que converta las modificaciones aadidas, clases y tratamiento rigurosode tipos, a lenguaje C. De hecho, el nombre de C++ le viene en parte porser considerado una evolucin natural del lenguaje C. En la actualidad, C++provee mecanismos suficientes para implementar, entre otras cosas, todos losconceptos de la POO de manera adecuada y, por supuesto, tiene su propiocompilador nativo, sin que ello sea obstculo para que, la mayora de los com-piladores de C++ existentes, tambin compilen C puro. Quizs sea este soporte

    de mltiples paradigmas una de las claves de su xito.Algunas de las caractersticas ms importantes de C++ son:

    Soporte de diferentes estilos de programacin.

    Espacios de nombres.

    Encapsulacin de informacin mediante el concepto de clases, apoyadotambin en los modificadores de acceso.

    12

  • 8/10/2019 POO con C++

    15/174

    libropoo 2011/2/19 19:02 page 13 #13

    CAPTULO 1. INTRODUCCIN

    Soporte de herencia simple y mltiple.

    Funciones virtuales, que posibilitan el polimorfismo.

    Sobrecarga de funciones y operadores.

    Soporte de excepciones.

    Biblioteca estndar, base para el desarrollo de un gran nmero de otrasbibliotecas.

    Programacin genrica mediante el soporte de plantillas.

    Como se puede apreciar, el lenguaje C++ va ms all del paradigma de pro-gramacin orientada a objetos. Sin embargo, en este libro nos vamos a centrarcasi exclusivamente en los conceptos y abstracciones propuestos por este pa-radigma. El fin ltimo de este libro es introducir al lector en la programacinorientada a objetos. Este no es el libro adecuado para el lector interesado enaprender en profundidad toda la potencia del lenguaje C++.

    1.3.1. Lenguaje de ejemplo

    El lenguaje C++ ha sido elegido por los autores de este libro para plasmarde forma prctica los conceptos de programacin orientada a objetos. Si bienes verdad que existen lenguajes orientados a objetos ms modernos y msajustados al paradigma de POO, hemos elegido C++ por las siguientes razones:

    Su gran expansin. Se trata de un lenguaje mundialmente aceptado, apesar de sus caractersticas ms peculiares.

    Sometido a un estndar. El estndar C++ (ISO/IEC 14882) se ratificen 1998. Gracias al proceso de estandarizacin que ha sufrido y a labiblioteca estndar C++, este lenguaje se ha convertido en un lenguajepotente, eficiente y seguro.

    Existe un gran nmero de compiladores y de entornos de desarrollo. Esun lenguaje que puede ser usado en diferentes plataformas y diversosdominios de aplicacin. Adems, posee un gran nmero de herramientasde desarrollo.

    Demanda profesional. Es un lenguaje muy demandado profesionalmente,sobre todo, en dominios en los que el rendimiento es un requisito funda-mental.

    13

  • 8/10/2019 POO con C++

    16/174

    libropoo 2011/2/19 19:02 page 14 #14

    CAPTULO 1. INTRODUCCIN

    1.4. Resumen

    Este captulo pretende situar al lector en el contexto que dio origen al para-digma de programacin orientada a objetos. El objetivo consiste en proporcio-nar una dimensin histrica a los conceptos introducidos por este paradigma,de manera que se pueda lograr una comprensin global de cada uno de ellos.En definitiva, este captulo indaga sobre las causas que motivaron el origen deestos conceptos, de esta nueva forma de representacin de la realidad.

    Por otra parte, se introduce el lenguaje C++ que va a servir de herramientapara llevar a la prctica todos los conceptos de programacin que presenta estelibro.

    14

  • 8/10/2019 POO con C++

    17/174

    libropoo 2011/2/19 19:02 page 15 #15

    Captulo 2

    Clases y objetos

    2.1. Concepto de clase y objeto

    El mundo est lleno de objetos: el coche, la lavadora, la mesa, el telfono,etc. El paradigma de programacin orientada a objetos proporciona las abs-tracciones necesarias para poder desarrollar sistemas software de una formams cercana a esta percepcin del mundo real.

    Mediante la POO, a la hora de tratar un problema, podemos descomponer-lo en subgrupos de partes relacionadas. Estos subgrupos pueden traducirse enunidades autocontenidas llamadasobjetos. Antes de la creacin de un objeto,se debe definir en primer lugar su formato general, su plantilla, que recibe elnombre declase. Por ejemplo, pensemos que estamos intentando construir unaaplicacin de dibujo de cuadrados. Nuestro programa va a ser capaz de pintarcuadrados con diferentes tamaos y colores: uno ser rojo y de 3 centmetrosde lado, otro verde y de 5 centmetros de lado, etc. Como podemos deducir,cada cuadrado est definido por dos caractersticas,lado y color, y contiene laoperacin dibuja. Desde el punto de vista de la POO, cada cuadrado se va arepresentar como un objeto de la clase Cuadrado que es la contiene las carac-tersticas y operaciones comunes de los objetos. En realidad, estamos creandoun nuevo tipo, el tipo Cuadrado, y cada variable de este tipo especial recibe elnombre de objeto.

    Una clase, por lo tanto, puede definirse como un tipo de datos cuyas va-riables son objetos o instancias de una clase. Puede decirse que el conceptode clase es esttico y el concepto de objeto es dinmico; ya que, slo existeen tiempo de ejecucin. Cada objeto de una clase comparte con el resto lasoperaciones, y a la vez posee sus propios valores para los atributos que posee:esto es, su estado. Las operaciones, tambin llamadas mensajes, se usarntanto para cambiar el estado de un objeto como para comunicar objetos entres mediante el paso de mensajes.

    15

  • 8/10/2019 POO con C++

    18/174

    libropoo 2011/2/19 19:02 page 16 #16

    CAPTULO 2. CLASES Y OBJETOS

    Un ejemplo de clase podra ser la clase Alumno, esta clase definira diferen-tes alumnos, en trminos de nombre,nmero de matrcula,curso,especialidad,localidad, etc... el alumno Juan Snchez con nmero de matrcula 5566432 serauna instancia de la claseAlumno. Otro ejemplo de clase podra ser la clase Tele-fono, esta clase definira diferentes telfonos con los datos nmero, tipo de tarifaasociada, nombre de usuario asociado, e importe acumulado por cada telfono.Una instancia de esta clase podra ser el telfono con nmero 927123456.

    2.1.1. Clases y objetos en C++

    La sintaxis de declaracin de una clase en el lenguaje C++ es muy parecida

    a la de las estructuras.class nombre de clase { cuerpo de la clase };

    El cuerpo de la clase est compuesto por los datos o atributos miembro ypor las operaciones o funciones miembro.

    Veamos cmo se implementara en C++, siguiendo los principios de la POO,la claseCuadrado de la aplicacin de dibujo de cuadrados.

    enum Color {rojo,verde,azul,amarillo,blanco,negro};

    class Cuadrado {

    int lado;

    Color color;

    public:

    void dibuja( );

    };

    Como se puede ver en el ejemplo, la clase Cuadrado contiene los atributosmiembro que caracterizan cada instancia de cuadrado y una funcin miembroque nos permite dibujar cada una de los objetos cuadrado.

    En el ejemplo anterior, slo se ha presentado la declaracin de la claseCuadrado. Para completar ese ejemplo, falta definir la funcin miembro dibuja.En C++, el formato de definicin de una funcin miembro es el siguiente:

    tipo nombre clase::nombre funcin (lista de parmetros) {

    //cuerpo de la funcin miembro

    }

    Como se puede ver en la definicin de una funcin miembro, la definicin debeincluir el nombre de la clase, esto se debe a que podra haber dos o ms clasesque tuvieran funciones miembro con el mismo nombre. El operador "::" utili-zado se llama operador de resolucin de alcance y se utiliza para indicar a quclase pertenece la funcin miembro. Nuestro ejemplo se completara entoncesde la siguiente manera.

    16

  • 8/10/2019 POO con C++

    19/174

    libropoo 2011/2/19 19:02 page 17 #17

    CAPTULO 2. CLASES Y OBJETOS

    void Cuadrado::dibuja( ){

    //Algoritmo para dibujar un cuadrado

    }

    Cuando se definen varios objetos de una misma clase, todos ellos compartenlas funciones miembro definidas en la clase. Los objetos se diferencian por losvalores que toman sus atributos. A este conjunto de atributos que distinguena unos objetos de otros se les llama estado del objeto. Por ejemplo, todoslos cuadrado comparten la misma definicin de la funcin dibuja, pero poseendiferentes valores de sus atributos miembro lado y color.

    2.1.2. El operador thisLa palabra clave thispuede utilizarse en cualquier mtodo de la clase para

    referirse al objeto actual. Cada vez que se llama a una funcin miembro, au-tomticamente se pasa un puntero al objeto que la llama. Se puede acceder aeste puntero utilizando this.

    Veamos el uso del operador this en el ejemplo anterior.

    class Cuadrado {

    int lado;

    Color color;

    public:

    void dibuja( );

    void modifica(int lado, Color color){this->lado = lado;

    this->color = color;

    }

    };

    Hemos introducido una nueva funcin miembro a la clase Cuadrado: la funcinmodifica. En el cuerpo de esta funcin estamos usando el operador this paradistinguir, en este caso, los atributos de los parmetros de la funcin modifica;ya que tienen el mismo nombre. Este ejemplo sencillo slo quiere poner demanifiesto la posibilidad de acceder al objeto actual a travs del puntero this.En el caso de no utilizarse en este ejemplo el puntero this, la modificacin no

    se habra producido en los atributos lado y color.

    2.2. Encapsulacin

    Una de los pilares bsicos de la POO es la encapsulacin de los datos.Segn los principios de este paradigma de programacin, el acceso a los datosde una clase debe realizarse de forma controlada, protegindolos de accesos nodeseados. Cuando se desarrolla una aplicacin, a veces es necesario ocultar los

    17

  • 8/10/2019 POO con C++

    20/174

    libropoo 2011/2/19 19:02 page 18 #18

    CAPTULO 2. CLASES Y OBJETOS

    tipos de datos usados para que el usuario permanezca independiente de losdetalles de los mismos. De esta manera, el usuario no es sensible a los cambiosque se puedan producir en los tipos de datos elegidos dentro de una clase.

    La encapsulacin en los lenguajes orientados a objeto suele lograrse al de-clarar algunos datos como privados. El acceso a estos datos sera siempre con-trolado; ya que, se hara siempre a travs de funciones miembro que realizaranlas modificaciones oportunas de una forma transparente al usuario.

    La encapsulacin es el mecanismo que enlaza el cdigo y los datos, a la vezque los asegura frente a accesos no deseados. La principal razn del uso de laencapsulacin es evitar el acceso directo a atributos de una clase desde fuerade la propia clase. Se busca, principalmente, que el acceso a estos atributos

    se realice siempre mediante funciones miembro de la propia clase. El acceso aciertos elementos de datos se puede controlar de forma estricta considerndolosprivados.

    Una vez presentado el concepto encapsulacin, se puede definir de nuevoun objeto como una entidad lgica que encapsula los datos y el cdigo quemanipula dichos datos. Dentro de un objeto, parte del cdigo y/o los datospuede ser privada al objeto y, por tanto, inaccesible desde fuera del mismo. Sepodr asegurar un acceso correcto al objeto utilizando las funciones miembrodel objeto para acceder a los datos privados. El acceso a los datos de una clasese establece por lo tanto a travs de los mtodos que implementa la propia clasey que pone a disposicin del usuario. Este mecanismo recibe el nombre de pasode mensajes o interfaz y es la forma de comunicacin que se establece entre

    objetos.

    2.2.1. Encapsulacin en C++. Modificadores de acceso

    Una clase puede contener tanto partes privadas como partes pblicas. Pordefecto, todos los elementos de la clase son privados, lo que significa que no sonaccesibles desde ninguna funcin que no sea miembro de la clase. El mecanismoaportado por C++ para conseguir la encapsulacin es la utilizacin de losmodificadores de accesoprivatey public. Los miembros privados ocultan lasestructuras de datos y los procedimientos internos de un objeto.

    Si se incluye el modificador de acceso private en la lista de atributos yfunciones miembro, todos los miembros que aparezcan a continuacin sernmiembros privados. Los atributos sern atributos miembro privados y las fun-

    ciones sern funciones miembro privadas.Por su parte, para hacer pblicas ciertas partes de una clase, se deben decla-

    rar a continuacin del modificador de accesopublic. Aunque el lenguaje C++permite tener atributos public, debe restringirse su utilizacin. En su lugar,por norma general, para lograr la encapsulacin de los datos, es aconsejablecrear todos los datos privados y proporcionar acceso a los mismos mediantefunciones pblicas. Introduciendo los modificadores de acceso, el formato dedeclaracin de una clase quedara as:

    18

  • 8/10/2019 POO con C++

    21/174

    libropoo 2011/2/19 19:02 page 19 #19

    CAPTULO 2. CLASES Y OBJETOS

    class nombre de clase {

    private:

    //miembros privados

    public:

    //miembros pblicos

    };

    Una clase podr tener el nmero que desee de secciones de cada tipo, aunquelo normal ser una seccin de cada tipo. La clusula private mostrada enel formato de declaracin de una clase es opcional, ya que los miembros queaparecen despus de la llave de apertura hasta la aparicin de una clusula

    distinta se consideran siempre miembros privados.Por un lado, las funciones que son pblicas o accesibles para otras clases

    forman el interfaz de una clase y son declaradas como public. Por otro lado,las funciones que no permiten el acceso desde otras clases, es decir, aquellascuyo uso es de tipo interno a la clase en la que estn definidas son declaradascomo private. Se puede decir que estas funciones estn ocultas para el restode clases.

    A continuacin, se introduce un nuevo ejemplo para mostrar el funciona-miento de los modificadores de acceso. La declaracin de la clase Telefono esla que se muestra a continuacin.

    class Telefono {

    string numero;string tipo_tarifa;

    string usuario;

    float importe;

    void inicializarImporte( );

    public:

    void actualizarImporte(float _importe);

    float obtenerImporte( );

    void visualizarUsuario( );

    };

    //definicin

    void Telefono::inicializarImporte() {

    importe=0;

    }void Telefono::actualizarImporte(float _importe) {

    if (_importe

  • 8/10/2019 POO con C++

    22/174

    libropoo 2011/2/19 19:02 page 20 #20

    CAPTULO 2. CLASES Y OBJETOS

    return importe;

    }

    void Telefono::visualizarUsuario( ) {

    cout

  • 8/10/2019 POO con C++

    23/174

    libropoo 2011/2/19 19:02 page 21 #21

    CAPTULO 2. CLASES Y OBJETOS

    por lo tanto para inicializar los atributos miembro que se deseen de un objetoy para realizar algn otro tipo de inicializacin que el usuario crea necesaria.

    2.3.1.1. Constructores en C++

    La definicin de un constructor se realiza como cualquier otra funcin miem-bro, teniendo en cuenta dos particularidades: La funcin constructor debe tenerel mismo nombre que la clase. Por ejemplo, en la clase Telefono, su constructorslo puede llamarseTelefono. Adems, la funcin constructor no puede devolverningn tipo de datos, incluyendo el tipo void.

    La sintaxis general de un constructor es la siguiente:

    nombre de clase::nombre de clase (lista de parmetros) {

    //inicializacin de datos miembro del objeto

    }

    Los constructores deben definirse siempre de tipo public; ya que, de otra forma,no podramos declarar ningn objeto como instancia de esa clase, al no poderinvocarse a su constructor.

    Para declarar e inicializar objetos de la clase Telefono se escribe el nombrede la clase (nombre del tipo) y el nombre del nuevo objeto a declarar, como sise tratara de otro tipo de variable, de la forma que aparece a continuacin:

    Telefono telefono1;

    De este modo, cuando se crea el objeto telefono1 de la clase Telefono, el com-pilador llama automticamente al constructor de la clase y se inicializan lasvariables de dicho objeto.

    Como se muestra en el formato de un constructor, ste se define de la mismaforma que cualquier otra funcin miembro, anteponiendo el nombre de la clase,escribiendo "::" y a continuacin el nombre del constructor, que es igual alnombre de la clase. Teniendo en cuenta adems que el constructor no puededevolver ningn tipo de datos.

    En el ejemplo de la clase Telefono, la definicin de su constructor podraser de la siguiente forma:

    Telefono::Telefono() { importe=0; }

    Este constructor podra utilizarse por ejemplo para inicializar el importede laclaseTelefono al valor cero.

    A veces es necesario inicializar los objetos de distinta forma. Por ejemplo,podra interesarnos que al crear un objeto sin parmetros se inicializaran lasvariables con ciertos valores y al crearlo con parmetros las variables tomaranlos valores de esos parmetros de entrada. En este caso, deberamos crear un

    21

  • 8/10/2019 POO con C++

    24/174

    libropoo 2011/2/19 19:02 page 22 #22

    CAPTULO 2. CLASES Y OBJETOS

    nuevo constructor, implementando otra funcin que recibiera parmetros deentrada. En nuestro ejemplo podramos definir un constructor que no recibieraparmetros de entrada e inicializara el dato importe a cero y otro que recibieratres parmetros e inicializara los datos con dichos parmetros. Realmente, nosestamos aprovechando de la capacidad de C++ para sobrecargar funciones.Ms adelante veremos qu significa la sobrecarga de funciones.

    class Telefono {

    string numero;

    string tipo_tarifa;

    string usuario;

    float importe;public:

    Telefono();

    Telefono (string _numero, string _tarifa, string _usuario);

    void actualizarImporte(float _importe);

    float obtenerImporte( );

    void visualizarUsuario( );

    };

    //definicin

    void Telefono::Telefono() { importe=0; }

    void Telefono::Telefono(string _numero,

    string _tarifa,

    string _usuario) {importe = 0;

    numero = _numero;

    tarifa = _tarifa;

    usuario = _usuario;

    }

    Un constructor que no recibe parmetros se llama constructor predetermina-do. El compilador de C++ genera automticamente este tipo de constructorcuando no incluimos ningn constructor en la declaracin de la clase, este cons-tructor se encarga de realizar una inicializacin bit a bit de los atributos delobjeto. Por lo tanto, aunque no definamos ningn constructor, hemos de serconscientes de que todas las clases tendrn una funcin miembro constructor

    por defecto. Por su parte, un constructor que recibe parmetros de entrada sellama constructor parametrizado. La definicin de ambos constructores hasido mostrada en el ejemplo anterior, donde se ha definido la clase Telefono.

    Las distintas formas de crear objetos utilizando los diferentes constructoresdefinidos para la clase son las siguiente:

    objeto; //por defecto

    objeto (parmetros); //parametrizado

    22

  • 8/10/2019 POO con C++

    25/174

    libropoo 2011/2/19 19:02 page 23 #23

    CAPTULO 2. CLASES Y OBJETOS

    Siguiendo nuestro ejemplo, podramos crear objetos de tipo Telefonoutilizandolos constructores definidos anteriormente.

    Telefono telefono1;

    Telefono telefono2("927123456", "Di", "Juan Snchez");

    El objeto telefono1 ha sido creado con el constructor por defecto, con lo cualslo se inicializa la variable miembro importe con valor cero, sin embargo,el objeto telefono2ha sido creado con el constructor parametrizado, de estaforma las variables miembro se han inicializado con los valores introducidos porparmetro en la creacin del objeto.

    Se pueden crear tambin arrays de objetos, de la misma forma que se de-claran arrays de otro tipo de variables:

    Telefono telefonoarray[6];

    Como se puede ver en el ejemplo, al crear el array de objetos no se pasanparmetros. En este caso se estara produciendo una llamada al constructorpor defecto.

    Como se puede observar, es til la definicin de un constructor por defec-to que realice las operaciones que creamos oportunas cuando se crean nuevosobjetos de forma que tengamos valores controlados de los atributos de estosnuevos. Adems, tiene sentido que el compilador sintetice el constructor pordefecto en caso de que no lo haya hecho el programador.

    2.3.1.2. Clasificacin de constructores

    Se pueden diferenciar diferentes tipos de constructores de objetos:

    Constructorpredeterminado, por defecto o por omisin. Es aquel cons-tructor que no requiere ningn argumento. Se aplica en el caso prede-terminado donde se declara un objeto sin especificar argumentos. Si noincluimos ningn constructor en una clase, el compilador generar unconstructor predeterminado que inicializar los atributos miembros conlos valores por defecto. Este constructor se invocar al declarar objetosde la clase. En el ejemplo, el constructor predeterminado ser:

    Telefono ();

    Constructorparametrizadou ordinario. Crea una nueva instancia de laclase e inicializa los datos miembro con los valores incluidos en la declara-cin. Pueden existir distintos constructores de este tipo, dependiendo delnmero de parmetros que incluyan en su definicin. En nuestro ejemplo,un constructor parametrizado podra ser de la siguiente forma:

    Telefono (string _numero,string _tarifa,string _usuario);

    23

  • 8/10/2019 POO con C++

    26/174

    libropoo 2011/2/19 19:02 page 24 #24

    CAPTULO 2. CLASES Y OBJETOS

    Constructorcopia. Se puede definir como un caso especial de constructorparametrizado. Recibe como parmetro una referencia a un objeto de lamisma clase. Se utiliza este constructor cuando utilizamos un objeto deuna clase para inicializar otro objeto de la misma clase. Cuando creamosun nuevo objeto utilizando un constructor copia, se crea este objeto enotra zona de memoria, es decir se hace una copia fsica del objeto. Esteconstructor tiene tanta importancia dentro del lenguaje C++ que si nolo define el programador, el compilador se encarga de sintetizar uno au-tomticamente que realiza la copia bit a bit del objeto. El formato delconstructor copia es de la siguiente forma:

    nombre_de_clase (const nombre_de_clase &objetonuevo);

    Este constructor es invocado automticamente cuando es necesario crearuna copia de un objeto, por ejemplo, en el paso de objetos como parme-tros por valor. Este caso constituye la fuente de muchos errores entre losprogramadores inexpertos de C++ y ser considerado con ms deteni-miento un poco ms adelante. A parte de este caso, tambin se invocarcuando creamos objetos de esta forma:

    Telefono telefono1; //constructor por defecto

    Telefono telefono2 = telefono1; //constructor copia

    telefono3(telefono1); //constructor copia

    El operador= en este caso no seala una asignacin, sino una invocacinal constructor copia; ya que, se est usando para declarar un nuevo objetoa partir de otro. Siguiendo con el ejemplo, para el caso de nuestra claseTelefono, el constructor copia sera:

    Telefono (const Telefono &tel);

    2.3.2. Destructores

    El complemento de un constructor es el destructor. Al igual que a veceses necesario realizar inicializaciones u otro tipo de acciones al crear un objeto,a veces necesitamos realizar ciertas acciones cuando el objeto se destruye. Una

    de las ocasiones en las que se hace necesario el uso de un destructor es cuandose necesita liberar los recursos previamente reservados.

    Algunos lenguajes orientados a objetos no definen explcitamente destruc-tores para sus objetos, sino que utilizan otros mecanismos para la liberacin delos recursos consumidos por los objetos. Un conocido mecanismo de esta ndolees el recolector de basura, que se encarga de liberar los recursos de forma au-tomtica y transparente al programador. La discusin asociada a la inclusino no de mecanismos de este tipo dentro del lenguaje queda fuera del alcance

    24

  • 8/10/2019 POO con C++

    27/174

    libropoo 2011/2/19 19:02 page 25 #25

    CAPTULO 2. CLASES Y OBJETOS

    de este libro, pero el lector interesado encontrar referencias sobre este temadentro de la bibliografa.

    2.3.2.1. Destructores en C++

    La forma de declarar un destructor es igual a la forma de declarar un cons-tructor con la excepcin de que va precedido del smbolo " ~" y que no puederecibir parmetros de entrada.

    Los mtodos constructores y destructores no se invocan especficamentedesde el programa, es el compilador el que realiza dicha invocacin. En el casodel constructor se realiza cuando se crea un objeto y en caso del destructor

    cuando finaliza el mbito de un objeto, es decir, cuando se sale de la funcindonde ha sido creado el objeto o cuando se elimina explcitamente dicho objeto.En nuestro ejemplo, el destructor para la clase Telefono se declarara de la

    siguiente forma:

    ~ Telefono ();

    En la definicin del destructor, se liberaran los recursos que se hubieran reser-vado a la hora de crear un objeto de la clase Telefono.

    Para finalizar con el concepto de destructor, es necesario volver a recordarque cuando finaliza el mbito de los objetos creados se invocar automtica-mente al destructor de cada uno de ellos, realizando las operaciones definidasen l, normalmente, liberando recursos. Por lo tanto, es muy importante con-

    trolar en todo momento cundo se van a crear y destruir los objetos de nuestraaplicacin, para evitar intentar acceder a un objeto que haya sido destruido.

    2.3.3. Ejemplo de creacin y eliminacin de objetos

    El siguiente ejemplo, que parte de una reduccin de la clase Telefono, tratade mostrar cmo se producen las distintas invocaciones de los constructores ydestructores al trabajar con objetos, haciendo hincapi en el peligro de no de-finir un constructor copia para algunas clases. Antes de comenzar, es necesariocomentar el hecho de que este ejemplo usa cadenas al modo C para reflejar elproblema de no definir los constructores copia en ciertos casos. Se podra haberusado un puntero a un objeto de una clase creada para este ejemplo, pero se hausado el puntero al tipo charpara reducir el tamao del ejemplo. No obstante,resear que el problema que se va a exponer se produce por el hecho de usaratributos miembro de una clase que reserven memoria dinmica, sin importarde qu tipo o clase sean los punteros. Finalmente, recomendar al lector el usode cadenas al estilo ANSI C++ mediante la clase string que forma parte dela librera estndar de C++ (esta librera se ver en el apndice de este libro).

    class Telefono {

    char *numero;

    25

  • 8/10/2019 POO con C++

    28/174

    libropoo 2011/2/19 19:02 page 26 #26

    CAPTULO 2. CLASES Y OBJETOS

    float importe;

    public:

    Telefono (); //constructor por defecto

    Telefono (char *_numero); //constructor parametrizado

    void mostrar();

    ~ Telefono (); //destructor

    };

    Telefono::Telefono () {

    numero = new char[4];

    strcpy(numero,"555");

    importe = 0;

    cout

  • 8/10/2019 POO con C++

    29/174

    libropoo 2011/2/19 19:02 page 27 #27

    CAPTULO 2. CLASES Y OBJETOS

    asignarle espacio en el montn (heap) cuando se crea un objeto de esta clase;por lo tanto, se le asigna espacio en los constructores. Adems, cuando se des-truya un objeto se debe liberar la memoria que ocupa el atributo numero de eseobjeto. Por esta razn, se invoca a delete sobre ese puntero en el destructor.En resumen, en nuestra implementacin hemos tenido cuidado con la gestinde memoria para este atributo. Por otro lado, en la funcin main se crean tresobjetos de la clase Telefono. El primero mediante el constructor por defecto,el segundo mediante el constructor parametrizado definido y el tercero se creadinmicamente como una copia del segundo, en el siguiente apartado se explicacon ms detalle la creacin y eliminacin dinmica de objetos. Observemos queno se ha definido el constructor copia. Veamos cul es la salida de este ejemplo.

    Constructor por defecto

    Constructor parametrizado

    Nmero: 555

    Nmero: 927123456

    Nmero: 927123456

    Destructor

    Nmero: 555

    Nmero: xxx

    Destructor

    Destructor

    Lo primero que aparecen son las dos llamadas a los constructores que corres-ponden a los dos primeros objetos Telefonoque se crean. Despus se muestra elcontenido de cada uno de los objetos. El contenido del objeto telefono3coincidecon el deltelefono2, ya que se trata de una copia del mismo. El problema surgecuando destruimos el objeto telefono3. Observemos que el destructor pone lacadena "xxx" en el espacio de memoria al que apunta el atributo numero decada objeto antes de liberar la memoria ocupada. Como podemos observar, alinvocar a la funcin mostrarsobre el objeto telefono2aparece la cadena "xxx"en lugar de "927123456", que era el valor que debera tener el atributonumerodel objetotelefono2. Por qu ha variado el valor del atributo numerodel obje-to telefono2? Viendo el cdigo, podemos concluir que algo ha pasado con esteatributo cuando hemos destruido el objetotelefono3. Volvamos a repasar cmose ha creado el objeto telefono3. Hemos dicho que era una copia del objetote-

    lefono2por lo que se ha debido crear a travs del constructor copia de la claseTelefono. Sin embargo, no hemos definido ningn constructor copia en esta cla-se, por lo que el compilador ha sintetizado uno que realiza una copia bit a bit.La copia bit a bit significa que para cada atributo se va a copiar el valor quealmacena a nivel de bit sin tener en cuenta el tipo del atributo. En este caso,para el atributo numero se va a copiar la direccin de memoria que contiene,que apuntar a la zona de memoria dinmica donde se guarda el valor de lacadena numero. Por lo tanto, el atributo numero del objeto telefono3toma el

    27

  • 8/10/2019 POO con C++

    30/174

    libropoo 2011/2/19 19:02 page 28 #28

    CAPTULO 2. CLASES Y OBJETOS

    valor de la direccin de memoria que guarda el valor de numero de telefono2.En conclusin, los atributos numero de ambos objetos apuntan a la mismaposicin de memoria, que es donde se guarda la cadena "927123456". De estaforma, al mostrar el numero de telefono3parece que todo funciona correcta-mente. Como ya intuamos, el problema surge al destruir telefono3. Al destruireste objeto, se libera la memoria que ocupa su atributonumero. El problema esque esa memoria era la misma a la que apunta el numero de telefono2. Por lotanto, al destruir el telefono3, estamos destruyendo el valor de dicho atributodetelefono2. La figura 2.1 expresa grficamente este comportamiento errneo,mostrando en colores la memoria reservada y la liberada.

    El problema surge porque la copia bit a bit no es capaz de crear copias de

    atributos que se encuentran en memoria dinmica, sino slo de los punterosque la direccionan. Por lo tanto, para evitar errores de este tipo es necesariodefinir el constructor copia siempre que vayamos a necesitar copias de un objeto.Debemos ser conscientes de que en el paso de objetos como parmetros por valoro el retorno de objetos por valor, el compilador crea una copia de los objetos.Este punto se comenta ms adelante porque suele ser fuente comn de errores.

    En nuestro ejemplo tenemos, por tanto, que definir un constructor copiaque realice correctamente la copia del atributonumero.

    Telefono::Telefono (const Telefono &tel) {

    numero=new char[strlen(tel.numero)+1];

    assert(numero); //finaliza el programa si error memoria

    strcpy(numero, tel.numero);

    importe=tel.importe;

    cout

  • 8/10/2019 POO con C++

    31/174

    libropoo 2011/2/19 19:02 page 29 #29

    CAPTULO 2. CLASES Y OBJETOS

    Figura 2.1: Diferencia entre copia bit a bit y constructor copia

    2.3.4. Creacin y eliminacin dinmica de objetos

    Al igual que para el resto de variables, existen dos formas de crear objetos:esttica y dinmicamente. En el primer caso, los objetos se crean en ciertaspartes del programa y son destruidos cuando salen de su mbito. El compiladorcontrola automticamente su creacin y destruccin. Este tipo de objetos sonlos que hemos visto hasta ahora. En el caso dinmico, es el propio programadorel que controla su creacin y destruccin mediante el uso de punteros a objetos.

    A la hora de crear objetos dinmicamente debemos utilizar, como para elresto de variables dinmicas en C++, los operadoresnew y delete. Mediantenewse crea un objeto dinmicamente y se invoca a su constructor, reservandola memoria necesaria para almacenar los atributos de dicho objeto. Con el ope-radordeletese invoca al destructor del objeto y se libera dicha memoria. Porlo tanto, el programador puede controlar el ciclo de vida de un objeto explci-tamente a travs de estos operadores. Utilizando la clase Telefono, podremos

    definir objetos dinmicos de la siguiente forma:

    Telefono *telefono3;

    telefono3 = new Telefono;

    Telefono *telefono3 = new Telefono ("927123456","Di","Juan");

    La operacin devuelve un puntero del tipo apropiado que se puede utilizar paraacceder a los miembros del objeto correspondiente. En este ejemplo, el acceso

    29

  • 8/10/2019 POO con C++

    32/174

    libropoo 2011/2/19 19:02 page 30 #30

    CAPTULO 2. CLASES Y OBJETOS

    a los miembros del puntero a objeto telefono3 se realiza de la misma formaque se accede desde un puntero a los campos de una estructura, utilizaremosel operador -> en lugar del operador ., usado en la definicin de un objetoesttico.

    Telefono *telefono3=new Telefono ("927123456","Di","Juan");

    telefono3->actualizarImporte(30);

    cout

  • 8/10/2019 POO con C++

    33/174

    libropoo 2011/2/19 19:02 page 31 #31

    CAPTULO 2. CLASES Y OBJETOS

    El paso de parmetros por defecto en C++ es el pasopor valor. Si pasamosuna variable como parmetro por valor, el compilador genera una copia de lavariable para que sea utilizada por la funcin, evitando que se modifique lavariable original. El pasopor referencia significa que no se pasa la variablecomo tal sino una referencia a la misma. Este tipo de paso de parmetrosse suele utilizar por dos motivos bsicos: uno, porque es ms eficiente y, dos,porque se desea modificar la variable desde dentro de la funcin. A su vez,existen dos formas de pasar una variable como parmetro por referencia: comoun puntero, es el formato heredado de C, y como referencia, formato introducidopor C++.

    Veamos un ejemplo:

    void funcion(int uno, int * dos, int& tres);

    Esta funcin declara tres parmetros distintos. El primero indica que el pasodel parmetro uno se hace por valor. Por su parte, los parmetros dos y tresse pasan por referencia: el dos, al formato de C, y el tres, al formato de C++.

    2.4.1. Paso de objetos por valor

    La manera por defecto en C++ de pasar objetos como parmetros a unafuncin es utilizando el paso por valor. En este caso, cuando se pasa un objetoa una funcin se crea una copia del mismo. El hecho de que se cree una copiadel nuevo objeto puede plantear la duda de si se llama al constructor del nuevo

    objeto y al destructor del mismo. Veremos la respuesta a esta pregunta con unejemplo:

    class Entero {

    int valor;

    public:

    Entero();

    Entero(int aux);

    void modificarValor(int _valor) {

    valor= _valor;

    }

    int obtener_Valor() {

    return valor;

    }~Entero();

    };

    Entero::Entero() {

    valor=0;

    cout

  • 8/10/2019 POO con C++

    34/174

    libropoo 2011/2/19 19:02 page 32 #32

    CAPTULO 2. CLASES Y OBJETOS

    valor= _valor;

    cout

  • 8/10/2019 POO con C++

    35/174

    libropoo 2011/2/19 19:02 page 33 #33

    CAPTULO 2. CLASES Y OBJETOS

    valor= entero.valor;

    cout

  • 8/10/2019 POO con C++

    36/174

    libropoo 2011/2/19 19:02 page 34 #34

    CAPTULO 2. CLASES Y OBJETOS

    int valor;

    public:

    Entero();

    Entero(int aux);

    void modificarValor(int _valor) {

    valor= _valor;

    }

    int obtener_Valor() {

    return valor;

    }

    ~Entero();};

    Entero::Entero() {

    valor=0;

    cout

  • 8/10/2019 POO con C++

    37/174

  • 8/10/2019 POO con C++

    38/174

    libropoo 2011/2/19 19:02 page 36 #36

    CAPTULO 2. CLASES Y OBJETOS

    Entero* suma(Entero* op2);

    Entero& suma(Entero& op2);

    Entero& incremento();

    ~Entero() { };

    };

    Entero* Entero::suma(Entero* op2) {

    int x = op2->obtenerValor();

    op2->modificarValor(valor+x);

    return op2; //bien

    }

    Entero& Entero::suma(Entero& op2) {

    int x = op2.obtenerValor();op2.modificarValor(valor+x);

    return op2; //bien

    }

    Entero& Entero::incremento() {

    Entero *resultado;

    resultado->modificarValor(valor+1);

    return resultado; //mal

    }

    void main() {

    Entero num1, num2(5);

    Entero *r1 = num1.suma(&num2);

    Entero r2 = num1.suma(num2);Entero r3 = num1.incremento();

    }

    Al ejemplo de la clase Entero le hemos aadido tres funciones que devuelvenobjetos de la clase Entero. La primera de ellas recibe un puntero a Enterocomo parmetro y devuelve un puntero aEntero. Este caso es correcto porque elpuntero que se devuelve (la memoria a la que apunta) ha sido creado fuera de lafuncinsuma. Ocurre lo mismo con la siguiente funcin sumaen la que se usan

    referencias en vez de punteros: una forma ms elegante, pero menos explcita.El mbito de la referencia que se devuelve, op2, es exterior a la funcin suma;por lo tanto, no se libera el espacio de memoria al que apunta esa referenciacuando se termina la funcin suma. En el caso de la funcin incremento, sinembargo, estamos cometiendo el error de intentar devolver una referencia aun objeto local a la funcin. Al ser local, este objeto se destruir al terminarla funcin incremento y estaremos devolviendo una referencia a una zona dememoria no definida.

    36

  • 8/10/2019 POO con C++

    39/174

    libropoo 2011/2/19 19:02 page 37 #37

    CAPTULO 2. CLASES Y OBJETOS

    2.5.2. Por valor

    Por otro lado, cuando una funcin devuelve un objeto por valor, se producela misma situacin que en el paso de parmetros por valor. El compiladorcrear una copia del objeto que se intenta devolver. Para lograr esta copia, elcompilador invoca al constructor copia del objeto que se intenta devolver. En elcaso, de que no exista constructor copia el compilador sintetiza uno que realizala copia bit a bit. Esta forma de actuar conlleva los problemas que ya se hancomentado anteriormente en este captulo. Por lo tanto, siempre que se quieradevolver un objeto por valor debemos asegurarnos de escribir el constructorcopia para su clase.

    El problema es que podemos estar intentando devolver objetos de una claseque no hemos escrito nosotros y de la cual no poseemos el cdigo fuente de ladefinicin, siendo imposible que evitemos los problemas derivados de la copia bita bit en algunos objetos. Por consiguiente, se recomienda evitar devolver objetospor valor. Adems, es menos eficiente que devolver objetos por referencia.

    No se ha incluido un ejemplo en este caso porque el comportamiento de invo-cacin a los destructores es similar al caso de pasar un objeto como parmetropor valor.

    2.6. Miembros estticos

    2.6.1. Atributos miembro estticos

    En ocasiones puede ser til que todos los objetos de una clase compartanun atributo, de manera que, por ejemplo, puedan comunicarse a travs de l.En C, se usaban variables globales, pero el uso de este tipo de variables acarreamuchos problemas. C++, por su parte, permite obtener el mismo resultadopero aprovechando las caractersticas de encapsulacin que ofrecen las clases.De este modo, podemos declarar atributos miembro que compartan la mismaposicin de almacenamiento para todos los objetos de una clase. Para lograrlosimplemente es necesario anteponer el modificadorstatic a la declaracin delatributo que queremos compartir.

    Veamos un ejemplo de uso de un atributo miembro esttico.

    class Inicializa {

    static int valor;public:

    void cambiar(int _valor) {

    valor = _valor;

    }

    void mostrar() {

    cout

  • 8/10/2019 POO con C++

    40/174

    libropoo 2011/2/19 19:02 page 38 #38

    CAPTULO 2. CLASES Y OBJETOS

    }

    };

    int Inicializa::valor=1;

    void main() {

    Inicializa objeto1, objeto2;

    objeto1.mostrar ();

    objeto2.mostrar ();

    objeto1.cambiar(6);

    objeto1.mostrar();

    objeto2.mostrar();

    }

    En la clase del ejemplo hemos declarado el atributo valor como esttico. Fi-jmonos en que es necesario definir tambin dicho atributo, no slo declararlocomo en el caso de un atributo no esttico. Para definirlo debemos referirnosa l a travs del nombre de la clase y del operador de resolucin de alcance.Adems, podemos aprovechar la definicin para asignarle el valor que debecontener por defecto.

    El resultado que aparece por pantalla es el siguiente:

    vale = 1

    vale = 1

    vale = 6

    vale = 6

    Como slo existe una copia del atributo valorpara todos los objetos de la claseInicializa, cuando invocamos a la funcin cambiarsobreobjeto1, se modifica lanica copia del atributo valory todos los objetos muestran el mismo valor.

    Un uso algo ms especializado del modificadorstaticconsiste en la creacinde constantes. Si junto al modificador staticusamos tambinconst, estaremoscreando una constante.

    class Constantes{

    static const ancho = 640;

    static const alto = 480;

    };

    2.6.2. Funciones miembro estticas

    Al igual que sucede con los atributos miembro, puede ser interesante, enun momento dado, poder invocar a una funcin sin tener que crear ningnobjeto. Por otra parte, tambin es importante que esa funcin no est aisladade la estructura de clases de nuestro sistema. Con este fin, el lenguaje C++permite declarar funciones miembro estticas. El programador debe indicar que

    38

  • 8/10/2019 POO con C++

    41/174

    libropoo 2011/2/19 19:02 page 39 #39

    CAPTULO 2. CLASES Y OBJETOS

    desea que una determinada funcin sea esttica anteponiendo a su declaracinel modificadorstatic.

    Las funciones miembro estticas pueden ser invocadas a partir de un ob-jeto como el resto de funciones miembro, aunque es ms normal invocarlasdirectamente a travs del operador de resolucin de alcance.

    class Entero {

    int valor;

    public:

    static bool esNatural(int entero){

    if (valor>0) return true; //Error

    return (entero >0);}

    };

    int main(){

    bool res1 = Entero::esNatural(5);

    Entero entero;

    bool res2 = entero.esNatural(3);

    }

    En este ejemplo, hemos definido la funcin miembro esttica esNatural en laclaseEntero. Como muestra el ejemplo, se produce un error si se intenta acce-der al atributo miembrovalor. De hecho, las funciones miembro estticas slopueden acceder a atributos miembro estticos. Este comportamiento es cohe-

    rente; ya que, si se puede invocar a esa funcin sin usar un objeto, entoncesel atributo miembro no esttico no existir. Por lo tanto, el compilador debeevitar que se produzca esta situacin. En el ejemplo, en la funcin main semuestran distintas formas de invocar a la funcin esNatural. La forma ms co-mn es usar el operador de resolucin de alcance ms el nombre de la clase,como se hace en la primera llamada del ejemplo.

    Otra caracterstica peculiar de las funciones miembro estticas es que sonlas nicas funciones miembro que no reciben el puntero this. Es obvio que nodeben recibirlo; ya que, si recordamos, el puntero thisapuntaba al objeto quese encontraba en ejecucin, sobre el que se invocaba la llamada de la funcinmiembro. En este caso no hay objeto, por lo tanto, tampoco hay puntero.

    Este tipo de funciones se usa para implementar distintas tcnicas de progra-

    macin como, por ejemplo, el patrn de diseo Singleton. Para ms informacinsobre los patrones de diseo se recomienda al lector consultar el apndice debibliografa.

    2.7. Sobrecarga

    La sobrecarga no es un principio de la programacin orientada a objetos,sino que ms bien se trata de un recurso sintctico del lenguaje. En este apar-

    39

  • 8/10/2019 POO con C++

    42/174

    libropoo 2011/2/19 19:02 page 40 #40

    CAPTULO 2. CLASES Y OBJETOS

    tado, no obstante, vamos a considerar la sobrecarga desde la ptica de la pro-gramacin orientada a objetos. En C++, es posible sobrecargar tanto funcionescomo operadores.

    2.7.1. Funciones sobrecargadas

    El lenguaje C++ permite definir funciones que tengan el mismo nombre.Esto es posible gracias a que C++ identifica a las funciones por su signatura,que est formada por el nombre de la funcin y el nmero y tipo de los pa-rmetros de la funcin. Por lo tanto, es posible tener funciones con el mismonombre siempre que se diferencien en el nmero o tipo de los parmetros.

    Como ejemplo podemos recuperar la clase Enteropresentada anteriormenteen el apartado de paso de objetos como parmetros y completarla un poco ms.

    class Entero {

    int valor;

    public:

    Entero();

    Entero(int _valor);

    Entero& suma(Entero& op2);

    Entero& suma(int op2);

    int suma(Entero& op2, int op3);

    ~Entero();

    };int main(){

    int x = 10;

    Entero ent,ent2(5);

    Entero ent3 = ent.suma(ent2);

    Entero ent4 = ent.suma(6);

    int x = ent.suma(ent4,x);

    }

    En este ejemplo, aparece la funcin miembro sumasobrecargada. Se aportandiferentes versiones de esta funcin variando el nmero y tipo de los parme-tros. El compilador puede distinguir en cada llamada a la funcin sumaa qucuerpo de funcin invocar segn el tipo de los parmetros. Realmente, ya hemos

    utilizado la sobrecarga de funciones a lo largo de este captulo para la definicinde distintos constructores para una misma clase.

    2.7.2. Operadores sobrecargados

    Al igual que C++ permite la sobrecarga de funciones, es decir la definicinde funciones que tienen el mismo nombre pero realizan operaciones distintas,permite tambin la sobrecarga en operadores, es decir, la utilizacin de los

    40

  • 8/10/2019 POO con C++

    43/174

    libropoo 2011/2/19 19:02 page 41 #41

    CAPTULO 2. CLASES Y OBJETOS

    mismos operadores pero aplicados con un nuevo significado. Un ejemplo desobrecarga es el operador "*", ya que se puede utilizar como operador quemultiplica dos nmeros y como operador para trabajar con punteros.

    Cuando un nuevo operador es sobrecargado, posee un nuevo significadopara la clase en la que se define, pero sigue conservando todos los significadosanteriores. La utilizacin de la sobrecarga de operadores tiene la ventaja desimplificar el uso de una clase y la escritura del cdigo; sin embargo, por otrolado, puede llegar a complicar demasiado la definicin de la clase. Debe tenerseen cuenta este inconveniente a la hora de utilizar sobrecarga de operadores; yaque, si su uso aade excesiva complejidad o confusin a los programas, es mejorno usarla.

    Para sobrecargar un operador se utiliza la palabra claveoperator. Es con-veniente tener en cuenta que uno de los operandos debe ser de la clase queredefine el operador. Tambin hay que ser conscientes del nmero de parme-tros que aceptar un operador. Los operadores pueden ser unarios, slo aceptanun parmetro, o binarios. En el siguiente ejemplo se muestra la sobrecarga deoperadores.

    En realidad, el tema de la sobrecarga de operadores es bastante ms comple-jo que lo comentado en este apartado. Si el lector est interesado en profundizaren este tema, le conviene revisar la bibliografa. El objetivo de este apartadoes introducir brevemente la capacidad de sobrecargar operadores dentro dellenguaje C++ con el fin nico de que el lector conozca su existencia.

    class punto3D {int x, y, z;

    public:

    punto3D(){x=y=z=0;}

    punto3D(int a, int b, int c);

    punto3D(const punto3D &p3);

    punto3D operator+(const punto3D& op2);

    punto3D operator+(int op2);

    int operator==(const punto3D& op2);

    punto3D &operator=(const punto3D& op2);

    ~punto3D(){};

    };

    punto3D::punto3D (int a, int b, int c){x=a;

    y=b;

    z=c;

    }

    punto3D::punto3D (const punto3D &p3){

    x=p3.x;

    y=p3.y;

    41

  • 8/10/2019 POO con C++

    44/174

    libropoo 2011/2/19 19:02 page 42 #42

    CAPTULO 2. CLASES Y OBJETOS

    z=p3.z;

    }

    int punto3D::operator==(const punto3D& op2){

    if ((x==op2.x)&&(y==op2.y)&&(z==op2.z))

    return 1;

    return 0;

    }

    punto3D punto3D::operator+(const punto3D &op2){

    int a=x+op2.x;

    int b=y+op2.y;

    int c=z+op2.z;

    return punto3D(a,b,c); //objeto temporal}

    punto3D punto3D::operator+(int op2){

    int a=x+op2;

    int b=y+op2;

    int c=z+op2;

    return punto3D(a,b,c); //objeto temporal

    }

    punto3D &punto3D::operator=(const punto3D &op2){

    x=op2.x;

    y=op2.y;

    z=op2.z;

    return (*this);}

    void main (void) {

    punto3D p1(10,20,30), p2(1,2,3), p3;

    if (p1==p2)

    cout

  • 8/10/2019 POO con C++

    45/174

    libropoo 2011/2/19 19:02 page 43 #43

    CAPTULO 2. CLASES Y OBJETOS

    //p3=10+p3;

    }

    En este ejemplo, hemos sobrecargado los operadores asignacin, sumay com-paracinpara la clase punto3D. Todos son operadores binarios, por lo tanto,reciben un solo parmetro de entrada: el segundo operando. El primer operandoes el objeto que est en ejecucin, sobre el que se invoca la versin sobrecargadadel operador correspondiente. Este hecho lo podemos observar en la implemen-tacin de cada una de las versiones de los operadores en las que se utilizanlos atributos miembro del objeto actual. Otra caracterstica interesante es laposibilidad de concatenar las llamadas a los operadores, como se muestra en el

    ejemplo con la suma y la asignacin. Tambin es importante tener en cuentael orden de los operandos cuando se quiere usar un operador sobrecargado. Sinos fijamos, la ltima operacin de suma del ejemplo da error. La razn deeste error consiste en que hemos sobrecargado el operador sumapara la clasepunto3D; por lo tanto, el primer operando debe ser un objeto de esta clase.

    2.8. Resumen

    En este captulo hemos sentado las bases para entender el paradigma deprogramacin orientada a objetos. Se han presentado los conceptos bsicos deobjeto y clase, as como el principio de la encapsulacin que es uno de los pilaresde la programacin orientada a objetos.

    La creacin y eliminacin de objetos constituye uno de los problemas mscomunes para los programadores novatos. Por lo tanto, se ha intentado expo-ner de forma prctica cada una de las caractersticas asociadas a este puntodentro del lenguaje C++. Especial atencin han tenido los diferentes tipos deconstructores, la explicacin de la creacin automtica de objetos por parte delcompilador y el paso de objetos como parmetros a funciones o su retorno.

    Para terminar se ha realizado una somera introduccin al concepto de so-brecarga, al que se regresar en captulos posteriores.

    43

  • 8/10/2019 POO con C++

    46/174

  • 8/10/2019 POO con C++

    47/174

    libropoo 2011/2/19 19:02 page 45 #45

    Captulo 3

    Mecanismos de reutilizacinUna de las principales motivaciones del origen de la programacin orientada

    a objetos consiste en definir nuevos conceptos y abstracciones en los lenguajesde programacin que faciliten la reutilizacin de cdigo y favorezcan la ex-tensibilidad de los sistemas software. La posibilidad de reutilizar cdigo es unobjetivo principal en cualquier equipo de desarrollo software; ya que, permite laconstruccin de nuevas aplicaciones o la modificacin de aplicaciones existentescon menor esfuerzo y coste.

    En la programacin estructurada no se introducen mecanismos explcitos dereutilizacin de cdigo; por lo tanto, las tcnicas utilizadas para la reutilizacinno iban mucho ms all del tradicional cortar y pegar. Evidentemente, sta noes una tcnica de reutilizacin demasiado fiable. Adems, tampoco se puedeusar para la reutilizacin de grandes porciones de cdigo.

    Para solventar en parte esta carencia, surge la POO. Como ya se ha co-mentado en captulos anteriores, en la POO el cdigo aparece estructuradoen clases. La clase constituye el eje sobre el que se definen los mecanismos dereutilizacin de cdigo. La reutilizacin de cdigo consiste en crear nuevas cla-ses a partir de clases ya construidas y depuradas, en vez de crearlas desde elprincipio: desarrollo incremental.

    En la POO existen dos mecanismos de reutilizacin de cdigo: la compo-siciny la herencia. En lo referente a la composicin, consiste simplementeen crear objetos de la clase reutilizada como atributos de la nueva clase. Se de-

    nomina composicin porque la nueva clase est compuesta de objetos de clasesque ya existan. En cuanto a la herencia, se basa en crear una nueva clase queespecializa una clase existente, aadindole nuevo cdigo sin modificar dichaclase base.

    Una de las ventajas de la herencia y la composicin es que posibilitan eldesarrollo incremental permitiendo introducir nuevo cdigo sin causar erroresen el cdigo existente. Si aparecen errores, stos estarn aislados dentro del nue-vo cdigo, que es mucho ms fcil y rpido de leer que si se hubiese modificado

    45

  • 8/10/2019 POO con C++

    48/174

    libropoo 2011/2/19 19:02 page 46 #46

    CAPTULO 3. MECANISMOS DE REUTILIZACIN

    el cuerpo del cdigo existente.Efectivamente, se produce una clara separacin entre las clases. En C++,

    por ejemplo, no se necesita el cdigo fuente de las funciones miembro parareutilizar su cdigo, simplemente el fichero cabecera de la clase y el ficheroobjeto o librera con las funciones miembro compiladas.

    La eleccin de la composicin y la herencia como mecanismos de reutiliza-cin de cdigo no se ha realizado de manera arbitraria, sino que se correspondecon la forma de clasificacin que sigue la mente humana. La mente humanaclasifica los conceptos de acuerdo a dos dimensiones: pertenencia y variedad.Desde este punto de vista, se puede decir que una cigea es un tipo de ave(variedad o una relacin del tipo es un) y que una pluma es parte de un ave

    (pertenencia o una relacin del tipo tiene un).Es importante resear que el desarrollo de un programa es un proceso incre-

    mental, al igual que el aprendizaje humano. Podremos realizar todo el anlisisdeseado, y aun as no se conocern todas las respuestas cuando se establezcael proyecto. Tendremos mucho ms xito si hacemos que nuestro proyecto vayacreciendo como una criatura orgnica y evolutiva, en lugar de construirlo deuna vez como un rascacielos de cristal.

    En resumen, a lo largo de este captulo, aprenderemos a reutilizar clasesya creadas y depuradas en la construccin de clases ms complejas y especia-lizadas, siguiendo un proceso de desarrollo incremental y usando para ello losconceptos de composicin y herencia introducidos por la POO.

    3.1. Composicin

    Este apartado est organizado como sigue. En primer lugar, se propone unproblema que se puede solucionar mediante composicin. Posteriormente, serealiza una exposicin de la composicin a nivel conceptual. Y, finalmente, seintroduce la composicin a nivel de cdigo en lenguaje C++, detallando losdiferentes casos a tener en cuenta.

    3.1.1. Problema

    Imaginemos, por ejemplo, que queremos construir una clase que sea capazde dibujar, trasladar y rotar en la pantalla un cubo en 3 dimensiones (cubo

    3D). A simple vista puede parecer una tarea compleja. Y, posiblemente, lo seasi abordamos su implementacin desde el principio sin ninguna base. Sin em-bargo, si pudisemos reutilizar cierto cdigo encargado de dibujar, trasladary rotar un segmento en pantalla todo sera ms fcil (desarrollo incremental).Realmente, un cubo 3D est formado por segmentos que intersectan entre s:aristas. Por lo tanto, si ya poseemos la capacidad de dibujar segmentos, lo nicoque hay que hacer es reutilizar esa funcionalidad para dibujar segmentos queformen un cubo 3D. La complejidad de dibujar un cubo en 3D se reduce a la

    46

  • 8/10/2019 POO con C++

    49/174

    libropoo 2011/2/19 19:02 page 47 #47

    CAPTULO 3. MECANISMOS DE REUTILIZACIN

    Figura 3.1: Mecanismo de composicin

    invocacin de la funcionalidad de dibujo de cada una de las aristas que lo com-ponen. No es necesario, entonces, volver a implementar complicadas rutinas dedibujo, sino que reutilizaremos las que ya tenamos perfectamente implemen-tadas y probadas. Este mismo proceso de reutilizacin se puede seguir para laconstruccin de la clase segmento a partir de una clase existente previamentedenominada punto 3D, como se aprecia en la figura 3.1.

    Como se puede deducir fcilmente, una vez implementadas y depuradas lasclases punto 3D y segmento 3D, pueden ser reutilizadas para la construccinde cualquier figura 3D. Al fin y al cabo, todas estas figuras estn compuestaspor segmentos y puntos 3D.

    47

  • 8/10/2019 POO con C++

    50/174

    libropoo 2011/2/19 19:02 page 48 #48

    CAPTULO 3. MECANISMOS DE REUTILIZACIN

    3.1.2. Concepto

    La composicin es el mecanismo ms sencillo de reutilizacin de cdigode la POO. Consiste bsicamente en crear nuevas clases a partir de clasesexistentes que actan como elementos compositores de las nuevas. Dadas lascaractersticas de modularidad de la POO, ni siquiera es necesario disponer delcdigo fuente de las clases que vamos a usar en la composicin de una nuevaclase, es suficiente con poseer su declaracin.

    Finalmente, es necesario ser consciente de que el hecho de relacionar dosobjetos mediante la composicin implica que entre ellos existe una relacinsemnticatiene un. En el ejemplo anterior, existe esta relacin entre segmentoy punto 3D, un segmento tiene puntos 3D, y entre figura y segmento, unafigura tiene segmentos. A la hora de decidir el uso de la composicin comomecanismo de reutilizacin, es necesario asegurarse de que existe esta relacinsemntica entre los objetos implicados. En caso de que no se pueda estableceresta relacin, no se debe usar la composicin, sino que debe hacerse uso delmecanismo de programacin adecuado a la situacin concreta.

    3.1.3. La composicin en C++

    El mecanismo de composicin no posee ninguna sintaxis especial dentro delos lenguajes orientados a objeto (a partir de ahora LOO). No existen palabrasreservadas dentro del lenguaje C++ para sealar la composicin. La compo-sicin es un mecanismo de reutilizacin de cdigo muy natural dentro de la

    estructura de cdigo inherente a la POO. De hecho, se trata del mecanis