Está en la página 1de 6

1.

-CONCEPTOS DE PROGRAMACIÓN ORIENTADA A OBJETOS


1.1 Introducción

Un concepto muy importante introducido por la programación estructurada es la abstracción. La abstracción se puede definir
como la capacidad de examinar algo sin preocuparse de los detalles internos. En un programa estructurado es suficiente
conocer que un procedimiento dado realiza una tarea específica. El cómo se realiza la tarea no es importante; mientras el
procedimiento sea fiable se puede utilizar sin tener que conocer cómo funciona su interior. Esto se conoce como abstracción
funcional.

Una debilidad de la programación estructurada aparece cuando programadores diferentes trabajan en una aplicación como un
equipo. Dado que programadores diferentes manipulan funciones separadas que pueden referirse a tipos de datos
mutuamente compartidos, los cambios de un programador se deben reflejar en el trabajo del resto del equipo. Otro problema
de la programación estructurada es que raramente es posible anticipar el diseño de un sistema completo antes de que se
implemente realmente.
En esencia, un defecto de la programación estructurada, como se acaba de ver, consiste en la separación conceptual de datos
y código. Este defecto se agrava a medida que el tamaño del programa crece.

1.2 Abstracción de datos

La abstracción de datos permite no preocuparse de los detalles no esenciales. Existe en casi todos los lenguajes de
programación. Las estructuras de datos y los tipos de datos son un ejemplo de abstracción. Los procedimientos y funciones
son otro ejemplo. Sólo recientemente han emergido lenguajes que soportan sus propios tipos abstractos de datos (TAD), como
Pascal, Ada, Modula-2 y C++.

1.3 ¿Qué es la programación orientada a objetos?

Se puede definir POO como una técnica o estilo de programación que utiliza objetos como bloque esencial de construcción.
Los objetos son en realidad como los tipos abstractos de datos. Un TAD es un tipo definido por el programador junto con un
conjunto de operaciones que se pueden realizar sobre ellos. Se denominan abstractos para diferenciarlos de los tipos de datos
fundamentales o básicos.
En C se puede definir un tipo abstracto de datos utilizando typedef y struct y la implementación de las operaciones con un
conjunto de funciones.

C++ tiene muchas facilidades para definir y utilizar un tipo TAD.

Al igual que los tipos de datos definidos por el usuario, un objeto es una colección de datos, junto con las funciones asociadas,
utilizadas para operar sobre esos datos. Sin embargo la potencia real de los objetos reside en las propiedades que soportan:
herencia, encapsulación y polimorfismo, junto con los conceptos básicos de objetos, clases, métodos y mensajes. 

1.4 Trabajando con objetos

En programación convencional los programas se dividen en dos componentes: procedimientos y datos. Este método permite
empaquetar código de programa en procedimientos, pero ¿Qué sucede con los datos? Las estructuras de datos utilizadas en
programación son globales o se pasan como parámetros. En esencia los datos se tratan separadamente de los
procedimientos.
En POO un programa se divide en componentes que contienen procedimientos y datos. Cada componente se considera un
objeto.

Un objeto es una unidad que contiene datos y las funciones que operan sobre esos datos . A los elementos de un objeto se les
conoce como miembros; las funciones que operan sobre los datos se denominan métodos (en C++ también se llaman
funciones miembro) y los datos se denominan miembros datos. En C++ un programa consta de objetos. Los objetos de un
programa se comunican entre sí mediante el paso o envío de mensajes (acciones que debe ejecutar el objeto).
En POO los objetos pueden se cualquier entidad del mundo real:

- Objetos físicos
 automóviles en una simulación de tráfico
 aviones en un sistema de control de tráfico aéreo
 animales mamíferos, etc

- Elementos de interfaces gráficos de usuarios


 ventanas
 iconos
 menús
 ratones

-Estructuras de datos
 arrays
 pilas
 árboles binarios

- Tipos de datos definidos por el usuario


 números complejos
 hora del día

1.5 Definición de objetos

Un objeto es una unidad que contiene datos y las funciones que operan sobre esos datos. Los datos se denominan miembros
dato y las funciones métodos o funciones miembro.
Los datos y las funciones se encapsulan en una única entidad. Los datos están ocultos y sólo mediante las funciones miembro
es posible acceder a ellos.

1.6 Clases

Una clase es un tipo definido por el usuario que determina las estructuras de datos y las operaciones asociadas con ese tipo.
Cada vez que se construye un objeto de una clase, se crea una instancia de esa clase. En general, los términos objetos e
instancias de una clase se pueden utilizar indistintamente.
Una clase es una colección de objetos similares y un objeto es una instancia de una definición de una clase.
La comunicación con el objeto se realiza a través del paso de mensajes. El envío a una instancia de una clase produce la
ejecución de un método o función miembro . El paso de mensajes es el término utilizado para referirnos a la invocación o
llamada de una función miembro de un objeto.

1.7 Mensajes: activación de objetos

Los objetos pueden ser activados mediante la recepción de mensajes. Un mensaje es simplemente una petición para que un
objeto se comporte de una determinada manera, ejecutando una de sus funciones miembro. La técnica de enviar mensajes se
conoce como paso de mensajes.

Estructuralmente un mensaje consta de tres partes:

- la identidad del objeto receptor


- la función miembro del receptor cuya ejecución se ha solicitado
- cualquier otra información adicional que el receptor pueda necesitar para ejecutar el método requerido.

En C++, la notación utilizada es nombre_del_objeto.función_miembro


Ejemplo: Se tiene un objeto o1 con los siguientes miembros dato: nombre_alumno y curso y con las funciones miembro:
leer_nombre e imprimir. Si el objeto o1 recibe el mensaje imprimir, esto se expresa:

o1.imprimir()

La sentencia anterior se lee: "enviar mensaje imprimir al objeto o1". El objeto o1 reacciona al mensaje ejecutando la función
miembro de igual nombre que el mensaje. El mensaje puede llevar parámetros:

o1.leer_nombre("Pedro Pérez")
Sin los mensajes los objetos que se definan no podrán comunicarse con otros objetos. Desde un punto de vista convencional,
el paso de mensajes no es más que el sinónimo de llamada a una función.

1.8 Programa orientado a objetos

Un programa orientado a objetos es una colección de clases. Necesitará una función principal que cree objetos y comience la
ejecución mediante la invocación de sus funciones miembro.
Esta organización conduce a separar partes diferentes de una aplicación en distintos archivos. La idea consiste en poner la
descripción de la clase para cada una de ellas en un archivo separado. La función principal también se pone en un archivo
independiente. El compilador ensamblará el programa completo a partir de los archivos independientes en una única unidad.

En realidad, cuando se ejecuta un programa orientado a objetos, ocurren tres acciones:


1. Se crean los objetos cuando se necesitan
2. Los mensajes se envían desde uno objetos y se reciben en otros
3. Se borran los objetos cuando ya no son necesarios y se recupera la memoria ocupada por ellos

 1.9 Herencia

La herencia es la propiedad que permite a los objetos construirse a partir de otros objetos.
Una clase se puede dividir en subclases. En C++ la clase original se denomina clase base; las clases que se definen a partir de
la clase base, compartiendo sus características y añadiendo otras nuevas, se denominan clases derivadas.
Las clases derivadas pueden heredar código y datos de su clase base añadiendo su propio código y datos a la misma.
La herencia impone una relación jerárquica entre clases en la cual una clase hija hereda de su clase padre. Si una clase sólo
puede recibir características de otra clase base, la herencia se denomina herencia simple.
Si una clase recibe propiedades de más de una clase base, la herencia se denomina herencia múltiple.

1.10 Polimorfismo

En un sentido literal, significa la cualidad de tener más de una forma. En el contexto de POO, el polimorfismo se refiere al
hecho de que una misma operación puede tener diferente comportamiento en diferentes objetos. Por ejemplo, consideremos la
operación sumar. El operador + realiza la suma de dos números de diferente tipo. Además se puede definir la operación de
sumar dos cadenas mediante el operador suma.
7.- HERENCIA Y JERARQUIA DE CLASES
7.1 Introducción

Una de las propiedades más importantes de la POO es la abstracción de datos. Esta propiedad se manifiesta esencialmente
en la encapsulación, que es la responsable de gestionar la complejidad de grandes programas al permitir la definición de
nuevos tipos de datos: las clases.

Sin embargo, la clase no es suficiente por sí sola para soportar diseño y programación orientada a objetos. Se necesita un
medio para relacionar unas clases con otras. Un medio son las clases anidadas, pero sólo se resuelve parcialmente el
problema, ya que las clases anidadas no tienen las características requeridas para relacionar totalmente una clase con otra. Se
necesita un mecanismo para crear jerarquías de clases en las que la clase A sea afín a la clase B, pero con la posibilidad de
poder añadirle también características propias. Este mecanismo es la herencia.

La herencia es, seguramente, la característica más potente de la POO, después de las clases. Por herencia conocemos el
proceso de crear nuevas clases, llamadas clases derivadas, a partir de una clase base.
En C++ la herencia se manifiesta con la creación de un tipo definido por el usuario (clase), que puede heredar las
características de otra clase ya existente o derivar las suyas a otra nueva clase. Cuando se hereda, las clases derivadas
reciben las características (estructuras de datos y funciones) de la clase original, a las que se pueden añadir nuevas
características o modificar las características heredadas. El compilador hace realmente una copia de la clase base en la nueva
clase derivada y permite al programador añadir o modificar miembros sin alterar el código de la clase base.
La derivación de clases consigue la reutilización efectiva del código de la clase base para sus necesidades. Si se tiene una
clase base totalmente depurada, la herencia ayuda a reutilizar ese código en una nueva clase. No es necesario comprender el
código fuente de la clase original, sino sólo lo que hace.

7.2 Clases derivadas


En C++, la herencia simple se realiza tomando una clase existente y derivando nuevas clases de ella. La clase derivada
hereda las estructuras de datos y funciones de la clase original . Además, se pueden añadir nuevos miembros a las clases
derivadas y los miembros heredados pueden ser modificados.
Una clase utilizada para derivar nuevas clases se denomina clase base, clase padre, superclase o ascendiente. Una clase
creada de otra clase se denomina clase derivada o subclase.
Se pueden construir jerarquías de clases, en las que cada clase sirve como padre o raíz de una nueva clase.

7.3 Conceptos fundamentales de derivación


C++ utiliza un sistema de herencia jerárquica. Es decir, se hereda una clase de otra, creando nuevas clases a partir de las
clases ya existentes. Sólo se pueden heredar clases, no funciones ordinarias n variables, en C++.
Una clase derivada hereda todos los miembros dato excepto, miembros dato estáticos, de cada una de sus clases base.

Una clase derivada hereda las funciones miembro de su clase base. Esto significa que se hereda la capacidad para llamar a
funciones miembro de la clase base en los objetos de la clase derivada.

Los siguientes elementos de la clase no se heredan: - Constructores


- Destructores
Las clases base diseñadas con el objetivo principal de ser heredadas por otras se - Funciones amigas
denominan clases abstractas. Normalmente, no se crean instancias a partir de
- Funciones estáticas de la clase
clases abstractas, aunque sea posible.
- Datos estáticos de la clase
7.4 La herencia en C++ - Operador de asignación
sobrecargado
En C++ existen dos tipos de herencia: simple y múltiple. La herencia simple es aquella en la que cada clase derivada hereda
de una única clase. En herencia simple, cada clase tiene un solo ascendiente. Cada clase puede tener, sin embargo, muchos
descendientes.
La herencia múltiple es aquella en la cual una clase derivada tiene más de una clase base. Aunque el concepto de herencia
múltiple es muy útil, el diseño de clases suele ser más complejo.
7.5 Creación de una clase derivada
Cada clase derivada se debe referir a una clase base declarada anteriormente. La declaración de una clase derivada tiene la
siguiente sintaxis:           class clase_derivada:<especificadores_de_acceso> clase_base  {...};
Los especificadores de acceso pueden ser: public, protected o private.

7.6 Clases de derivación


Los especificadores de acceso a las clases base definen los posibles tipos de derivación: public, protected y private. El tipo de
acceso a la clase base especifica cómo recibirá la clase derivada a los miembros de la clase base. Si no se especifica un
acceso a la clase base, C++ supone que su tipo de herencia es privado.

 Derivación pública (public). Todos los miembros public y protected de la clase base son accesibles en la clase derivada,
mientras que los miembros private de la clase base son siempre inaccesibles en la clase derivada.
 Derivación privada (private). Todos los miembros de la clase base se comportan como miembros privados de la clase
derivada. Esto significa que los miembros public y protected de la clase base no son accesibles más que por las funciones
miembro de la clase derivada. Los miembros privados de la clase siguen siendo inaccesibles desde la clase derivada.
 Derivación protegida (protected). Todos los miembros public y protected de la clase base se comportan como miembros
protected de la clase derivada. Estos miembros no son, pues, accesibles al programa exterior, pero las clases que se
deriven a continuación podrán acceder normalmente a estos miembros (datos o funciones).

7.7 Constructores y destructores en herencia


Una clase derivada puede tener tanto constructores como destructores, aunque tiene el problema adicional de que la clase
base puede tomar ambas funciones miembro especiales. Un constructor o destructor definido en la clase base debe estar
coordinado con los encontrados en una clase derivada. Igualmente importante es el movimiento de valores de los miembros de
la clase derivada a los miembros que se encuentran en la base. En particular, se debe considerar cómo el constructor de la
clase base recibe valores de la clase derivada para crear el objeto completo.

Si un constructor se define tanto para la clase base como para la clase derivada, C++ llama primero al constructor base.
Después que el constructor de la base termina sus tareas, C++ ejecuta el constructor derivado.
Cuando una clase base define un constructor, éste se debe llamar durante la creación de cada instancia de una clase derivada,
para garantizar la buena inicialización de los datos miembro que la clase derivada hereda de la clase base. En este caso la
clase derivada debe definir a su vez un constructor que llama al constructor de la clase base proporcionándole los argumentos
requeridos.

Un constructor de una clase derivada debe utilizar un mecanismo de pasar aquellos argumentos requeridos por el
correspondiente constructor de la clase base.

                    derivada::derivada(tipo1 x, tipo2 y):base (x,y)    {...}

Otro aspecto importante que es necesario considerar es el orden en el que el compilador C++ inicializa las clases base de una
clase derivada. Cuando El compilador C++ inicializa una instancia de una clase derivada, tiene que inicializar todas las clases
base primero. Por definición, un destructor de clases no toma parámetros. Al contrario que los constructores, una función
destructor de una clase derivada se ejecuta antes que el destructor de la clase base.

7.8 Redefinición de funciones miembro heredadas


Se pueden utilizar funciones miembro en una clase derivada que tengan el mismo nombre que otra de una clase base.
La redefinición de funciones se realiza mediante funciones miembro sobrecargadas en la clase derivada. Una función miembro
redefinida oculta todas las funciones miembro heredadas del mismo nombre. Por tanto cuando en la clase base y en la clase
derivada hay una función con el mismo nombre en las dos, se ejecuta la función de la clase derivada.

7.9 Herencia múltiple


Es la propiedad con la cual una clase derivada puede tener más de una clase base . Es más adecuada para definir objetos que
son compuestos, por naturaleza, tales como un registro personal, un objeto gráfico.
Sólo es una extensión de la sintaxis de la clase derivada. Introduce una cierta complejidad en el lenguaje y el compilador, pero
proporciona grandes beneficios.
                        class ejemplo: private base1, private base2   {...};

La aplicación de clases base múltiples introduce un conjunto de ambigüedades a los programas C++. Una de las más comunes
se da cuando dos clases base tienen funciones con el mismo nombre, y sin embargo, una clase derivada de ambas no tiene
ninguna función con ese nombre. ¿ Cómo acceden los objetos de la clase derivada a la función correcta de la clase base ? El
nombre de la función no es suficiente, ya que el compilador no puede deducir cuál de las dos funciones es la invocada.

Si se tiene una clase C que se deriva de dos clases base A y B, ambas con una función mostrar() y se define un objeto de la
clase C: C objetoC, la manera de resolver la ambigüedad es utilizando el operador de resolución de ámbito:
objetoC.A::mostrar(); //se refiere a la versión de //mostrar() de la clase A
objetoC.B::mostrar(); //se refiere a la versión de //mostrar() de la clase B

7.10 Constructores y destructores en herencia múltiple


El uso de funciones constructor y destructor en clases derivadas es más complejo que en una clase simple. Al crear clases
derivadas con una sola clase base, se observa que el constructor de la clase base se llama siempre antes que el constructor
de la clase derivada.

Además se dispone de un mecanismo para pasar los valores de los parámetros necesarios al constructor base desde el
constructor de la clase derivada. Así, la sentencia siguiente pasa el puntero a carácter x y el valor del entero y a la clase base:
                 derivada (char *x, int y, double z): base(x,y)

Este método se expande para efectuar más de una clase base.La sentencia:
     derivada (char *x,int y, double z): base1(x),base2(y)

Llama al constructor base1 y pasa el valor de cadena de caracteres x y al constructor base2 le proporciona un valor entero y.
Como con la herencia simple, los constructores de la clase base se llaman antes de que se ejecuten al constructor de la clase
derivada. Los constructores se llaman en el orden en que se declaran las clases base.
De modo similar, las relaciones entre el destructor de la clase derivada y el destructor de la clase base se mantiene. El
destructor derivado se llama antes de que se llame a los destructores de cualquier base. Los destructores de las clases base
se llaman en orden inverso al orden en que los objetos base se crearon.

7.11 Herencia repetida


La primera regla de la herencia múltiple es que una clase derivada no puede heredar más de una vez de una sola clase, al
menos no directamente. Sin embargo, es posible que una clase se pueda derivar dos o más veces por caminos distintos, de
modo que se puede reprtir una clase. La propiedad de recibir por herencia una misma clase más de una vez se conoce como
herencia repetida.

7.12 Clases base virtuales


Una clase base virtual es una clase que es compartida por otras clases base con independencia del número de veces que esta
clase se produce en la jerarquía de derivación. Suponer , por ejemplo, que la clase T se deriva de las clases C y D cada una de
las cuales se deriva de la clase A. Esto significa que la clase T tiene dos instancias de A en su jerarquía de derivación. C++
permite instancias múltiples de la misma clase base. Sin embargo, si sólo se desea una instancia de la clase A para la clase T,
entonces se debe declarar A como una clase base virtual.
Las clases base virtuales proporcionan un método de anular el mecanismo de herencia múltiple, permitiendo especificar una
clase que es una clase base compartida.
Una clase derivada puede tener instancias virtuales y no virtuales de la misma clase base.

También podría gustarte