Sunteți pe pagina 1din 95

SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 1

FUNCIONES
La Función es una porción de código, un conjunto de sentencias, agrupadas por separado,
generalmente enfocadas a realizar una tarea específica.

También se suelen denominar subrutinas o subprogramas.

Ventajas:

La división de un programa en unidades más pequeñas o funciones presenta las siguientes


ventajas:

 Modularización: Es el proceso consistente en dividir un programa en una serie de


módulos más pequeños y manejables, llamados funciones. Cada función tiene una
misión muy concreta, de modo que nunca tiene un número de líneas excesivo.
 Ahorro de memoria y tiempo de desarrollo: En la medida en que una función es
utilizada muchas veces, el número total de líneas de código disminuye.
 Independencia de datos y ocultamiento de información: Una función es capaz de
mantener gran independencia con el resto del programa, manteniendo sus propios
datos y definiendo muy claramente la interfaz o comunicación con la función que le
ha llamado.

1.1 PROPIEDADES DE UNA FUNCION.

Desde el punto de vista de la definición matemática una función debe cumplir con las
siguientes propiedades:

 Tiene un nombre. El nombre de la función identifica de manera sintética, es decir en


una sola secuencia de caracteres, la tarea u operación especifica que desarrolla.
 Retorna un resultado. Como el conjunto de código contenido en una función
resuelve una tarea específica, entonces el resultado de dicha operación debe ser el
retorno de la misma. Si bien por la naturaleza de la estructuración de un programa
se desea desarrollar una función que no retorna resultado se la debe considerar
como un procedimiento, para lo cual se dispone de los mecanismos adecuados que
permitan su implementación.
 Se aplica a uno o mas parámetros o argumentos. La tarea específica que se
desarrolla y resuelve en una función debe ser aplicada a uno o mas datos con los
que trabaja la función, estos elementos son los parámetros o argumentos de la
función.

La utilización de funciones nos permite dividir un programa extenso en pequeños


segmentos que realizan tareas concretas. Probablemente, dentro de un mismo programa se
M.Cs. Ing. Julio Cesar Bermudez Vargas Página 1
SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

realicen las mismas tareas varias veces, lo que se facilita mediante la utilización de
funciones. Sin embargo, es probable que ciertas funciones no sean reutilizables, pero al
usarlas se mejora la legibilidad del programa.

Con el propósito de permitir un manejo eficiente de los datos, las funciones en C no se


pueden anidar. En otras palabras, una función no se puede declarar dentro de otra función,
por lo que todas las funciones son globales o externas, lo que hace que puedan llamarse
desde cualquier parte de un programa.

1.2. FUNCIONES EN C++.

La estructura general de una función en C es la siguiente:

tipo_de_retorno nombre_de_la_función (lista_de_parámetros)


{
cuerpo_de_la_función
return expresión
}

Donde:

 tipo_de_retorno: es el tipo del valor devuelto por la función, o, en caso de que la


función no devuelva valor alguno, la palabra reservada void.
 nombre_de_la_función: es el nombre o identificador asignado a la función.
 lista_de_parámetros: es la lista de declaración de los parámetros que son pasados a
la función. Éstos se separan por comas. Debemos tener en cuenta que pueden existir
funciones que no utilicen parámetros.
 cuerpo_de_la_función: está compuesto por un conjunto de sentencias que llevan a
cabo la tarea específica para la cual ha sido creada la función.
 return expresión: mediante la palabra reservada return, se devuelve el valor de la
función, en este caso representado por expresión.

Vamos a suponer que queremos crear un programa para calcular el precio de un producto
basándose en el precio base del mismo y el impuesto aplicable. A continuación mostramos
el código fuente de dicho programa:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 2


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <stdio.h>

float precio(float base, float impuesto); /* declaración */


main()
{
float importe = 2.5;
float tasa = 0.07;
printf("El precio a pagar es: %.2f\n", precio(importe, tasa));
return 0;
}

float precio(float base, float impuesto) /* definición */


{
float calculo;
calculo = base + (base * impuesto);
return calculo;
}

El ejemplo anterior se compone de dos funciones, la función requerida main y la función


creada por el usuario precio, que calcula el precio de un producto tomando como
parámetros su precio base y el impuesto aplicable. La función precio calcula el precio de un
producto sumándole el impuesto correspondiente al precio base y devuelve el valor
calculado mediante la sentencia return.

Por otra parte, en la función main declaramos dos variables de tipo float que contienen el
precio base del producto y el impuesto aplicable. La siguiente sentencia dentro de la
función main es la llamada a la función de biblioteca printf, que recibe como parámetro
Una llamada a la función precio, que devuelve un valor de tipo float. De esta manera, la
función printf imprime por la salida estándar el valor devuelto por la función precio. Es
importante tener en cuenta que las variables importe y tasa (argumentos) dentro de la
función main tienen una correspondencia con las variables base e impuesto (parámetros)
dentro de la función precio respectivamente.

1.3. DECLARACIÓN DE UNA FUNCIÓN.

Antes de empezar a utilizar una función debemos declararla. La declaración de una


función se conoce también como prototipo de la función. En el prototipo de una función se
tienen que especificar los parámetros de la función, así como el tipo de dato que devuelve.

Los prototipos de las funciones que se utilizan en un programa se incluyen generalmente en


la cabecera del programa y presentan la siguiente sintaxis:

tipo_de_retorno nombre_de_la_función(lista_de_parámetros);

En el prototipo de una función no se especifican las sentencias que forman parte de la


misma, sino sus características. Por ejemplo:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 3


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int cubo(int numero);

En este caso se declara la función cubo que recibe como parámetro una variable de tipo
entero (numero) y devuelve un valor del mismo tipo. En ningún momento estamos
especificando qué se va a hacer con la variable numero, sólo declaramos las características
de la función cubo.

Cabe señalar que el nombre de los parámetros es opcional y se utiliza para mejorar la
comprensión del código fuente. De esta manera, el prototipo de la función cubo podría
expresarse de la siguiente manera:

int cubo(int);

Los prototipos de las funciones son utilizados por el compilador para verificar que se
accede a la función de la manera adecuada con respecto al número y tipo de parámetros, y
al tipo de valor de retorno de la misma. Veamos algunos ejemplos de prototipos de
funciones:

int potencia(int base, int exponente);


double area_rectangulo (float base, float altura);
int mayor(int, int);

1.4. DEFINICION DE UNA FUNCION.

Luego de declarar una función, el siguiente paso es implementarla. Generalmente, este paso
se conoce como definición. Es precisamente en la definición de una función donde se
especifican las instrucciones que forman parte de la misma y que se utilizan para llevar a
cabo la tarea específica de la función. La definición de una función consta de dos partes:

El encabezado y el cuerpo de la función. En el encabezado de la función, al igual que en


el prototipo de la misma, se tienen que especificar los parámetros de la función, si los
utiliza y el tipo de datos que devuelve, mientras que el cuerpo se compone de las
instrucciones necesarias para realizar la tarea para la cual se crea la función. La sintaxis de
la definición de una función es la siguiente:

tipo_de_retorno nombre_de_la_función(lista_de_parámetros)
{
sentencias;
}

El tipo_de_retorno representa el tipo de dato del valor que devuelve la función. Este tipo
debe ser uno de los tipos simples de C, un puntero a un tipo de C o bien un tipo struct. De
forma predeterminada, se considera que toda función devuelve un tipo entero (int). En otras
palabras, si en la declaración o en la definición de una función no se especifica el
tipo_de_retorno, el compilador asume que devuelve un valor de tipo int.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 4


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El nombre_de_la_función representa el nombre que se le asigna a la función.

Se recomienda que el nombre de la función esté relacionado con la tarea que lleva a cabo.
En caso de que la función utilice parámetros, éstos deben estar listados entre paréntesis a
continuación del nombre de la función, especificando el tipo de dato y el nombre de cada
parámetro. En caso de que una función no utilice parámetros, se pueden dejar los paréntesis
vacíos o incluir la palabra void, que indica que la función no utiliza parámetros. Después
del encabezado de la función, debe aparecer, delimitado por llaves ({ y }), el cuerpo de la
función compuesto por las sentencias que llevan a cabo la tarea específica de la función.
Veamos la definición de la función cubo declarada
en el apartado anterior:

int cubo(int base)


{
int potencia;
potencia = base * base * base;
return potencia;
}

Es muy importante hacer notar que la definición de la función de la puede realizar después
de la función principal ‘main’, en este caso es necesario la declaración del prototipo o
simplemente antes de la función ‘main’.

A continuación mostramos las dos situaciones:

Con la declaración de un prototipo:

#include <stdio.h>

int cubo(int base);

main()
{
int numero;
for(numero=1; numero<=5; numero++)
{
printf("El cubo del número %d es %d\n", numero, cubo(numero));
}
return 0;
}
int cubo(int base)
{
int potencia;
potencia = base * base * base;
return potencia;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 5


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Con la definición de la función:

#include <stdio.h>

int cubo(int base)


{
int potencia;
potencia = base * base * base;
return potencia;
}

main()
{
int numero;
for(numero=1; numero<=5; numero++)
{
printf("El cubo del número %d es %d\n", numero, cubo(numero));
}
return 0;
}

1.5. ACCESO O LLAMADA A UNA FUNCION.

Para que una función realice la tarea para la cual fue creada, debemos acceder o llamar a la
misma. Cuando se llama a una función dentro de una expresión, el control del programa se
pasa a ésta y sólo regresa a la siguiente expresión de la que ha realizado la llamada cuando
encuentra una instrucción return o, en su defecto, la llave de cierre al final de la función.

Generalmente, se suele llamar a las funciones desde la función main, lo que no implica que
dentro de una función se pueda acceder a otra función.

Cuando queremos acceder a una función, debemos hacerlo mediante su nombre seguido de
la lista de argumentos que utiliza dicha función encerrados entre paréntesis. En caso de que
la función a la que se quiere acceder no utilice argumentos, se deben colocar los paréntesis
vacíos.

Cualquier expresión puede contener una llamada a una función. Esta llamada puede ser
parte de una expresión simple, como una asignación, o puede ser uno de los operandos de
una expresión más compleja. Por ejemplo:

a = cubo(2);
calculo = b + c / cubo(3);

Debemos recordar que los argumentos que utilizamos en la llamada a una función
sedenominan argumentos reales o parámetros actuales. Estos argumentos deben
coincidir en el número y tipo con los argumentos formales o parámetros de la función.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 6


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

No olvidemos que los argumentos formales son los que se utilizan en la definición y/o
declaración de una función.

Los argumentos reales pueden ser variables, constantes o incluso expresiones más
complejas.

El valor de cada argumento real en la llamada a una función se transfiere a dicha función y
se le asigna al argumento formal correspondiente.

Generalmente, cuando una función devuelve un valor, la llamada a la función suele estar
dentro de una expresión de asignación, como operando de una expresión compleja o como
argumento real de otra función. Sin embargo, cuando la función no devuelve ningún valor,
la llamada a la función suele aparecer sola. Veamos un ejemplo:

z = potencia( a, b);
imprime_valores (x, y, z);

1.6. VARIABLES L.OCALES.

Cuando declaramos variables dentro de la función principal del programa, es decir, dentro
de la función main, están únicamente asociadas a esta función, en otras palabras, son
variables locales de la función main y no se puede acceder a ellas a través de ninguna otra
función.

Al igual que sucede con las variables declaradas dentro de la función main, cualquier
variable que declaremos dentro de una función, es local a esa función, es decir, su ámbito
esta confinado a dicha función. Esta situación permite que existan variables con el mismo
nombre en diferentes funciones y que no mantengan ninguna relación entre sí.

Debemos tener en cuenta que cualquier variable declarada dentro de una función se
considera como una variable automática (auto) a menos que utilicemos algún modificador
de tipo.

El siguiente ejemplo ilustra el manejo de variables locales en funciones diferentes:

#include <stdio.h>

void imprimeValor()
{
int contador = 5; // variable local
printf("El valor de contador es: %d\n", contador);
}

main()
{
int contador = 0; //variable local
contador++;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 7


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

printf("El valor de contador es: %d\n", contador);


imprimeValor();
printf("Ahora el valor de contador es: %d\n", contador);
return 0;
}

1.7. VARIABLES GLOBALES.

A diferencia de las variables locales cuyo ámbito estaba confinado a la función donde
estaban declaradas, el ámbito de las variables globales se extiende desde el punto en el que
se definen hasta el final del programa. En otras palabras, si definimos una variable al
principio del programa, cualquier función que forme parte de éste podrá utilizarla
simplemente haciendo uso de su nombre.

La utilización de variables globales proporciona un mecanismo de intercambio de


información entre funciones sin necesidad de utilizar argumentos. Por otra parte, las
variables globales mantienen el valor que se les ha asignado dentro de su ámbito, incluso
después de finalizar las funciones que modifican dicho valor. Debemos tener en cuenta que
el uso de variables globales para el intercambio de informaciones entre funciones puede
resultar útil en algunas situaciones (como cuando se desea transferir más de un valor desde
una función), pero su utilización podría llevarnos a programas de difícil interpretación y
complejos de depurar.

En el siguiente ejemplo ilustramos el uso de una variable global:

#include <stdio.h>

int variable; // variable global

void unaFuncion()
{
printf("En la función unaFuncion, variable es: %d\n", variable);
}
void otraFuncion()
{
variable++;
printf("En la función otraFuncion, variable es: %d\n",variable);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 8


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

main()
{
variable = 9;
printf("El valor de variable es: %d\n", variable);
unaFuncion();
otraFuncion();
printf("Ahora el valor de variable es: %d\n", variable);
return 0;
}

1.8. PASO DE PARAMETROS POR VALOR Y POR REFERNCIA.

En C++ todos los argumentos que se pasan a una función se pasan por valor. En otras
palabras, se pasa una copia del valor del argumento y no el argumento en sí (por ello, este
procedimiento se conoce en algunas ocasiones como paso por copia). Al pasar una copia
del argumento original a la función, cualquier modificación que se realice sobre esta copia
no tendrá efecto sobre el argumento original utilizado en la llamada de la función. Se puede
considerar un argumento pasado por valor como una variable local de la función a la que se
ha pasado, de tal modo que los cambios que se realicen sobre ésta tendrán efecto sólo
dentro de la función.

Veamos un ejemplo del paso por valor de argumentos a una función:

#include <stdio.h>

void modificar(int variable); // PROTOTIPO

main()
{
int i = 1;
printf("\ni=%d antes de llamar a la función modificar", i);
modificar(i);
printf("\ni=%d después de llamar a la función modificar", i);
}

void modificar(int variable)


{
printf("\nvariable = %d dentro de modificar", variable);
variable = 9;
printf("\nvariable = %d dentro de modificar", variable);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 9


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Dado que lo que se pasa a la función modificar es una copia de la variable i, el valor de ésta
en la función main no se ve alterado cuando dentro de la función modificar se cambia el
valor de variable. De ahí, la salida del ejemplo anterior es la siguiente:

i=1 antes de llamar a la función modificar


variable = 1 dentro de modificar
variable = 9 dentro de modificar
i=1 después de llamar a la función modificar

Como ya hemos visto, cuando se pasa un argumento por valor, realmente se pasa una copia
de éste, y si esta copia se modifica el argumento original no se ve alterado. Sin embargo, en
muchas ocasiones lo que queremos es que una función cambie los valores de los
argumentos que le pasamos. Para lograrlo se utiliza lo que se conoce como paso de
parámetros por referencia. En estos casos, no se pasa una copia del argumento, sino el
argumento mismo.

Cuando realizamos un paso de parámetros por referencia en C++, realmente lo que


estamos pasando son direcciones de memoria. En otras palabras, lo que le pasamos a la
función son las direcciones de memoria de los argumentos.

Como hemos visto en la unidad anterior, esta operación se logra mediante la utilización del
operador de dirección ‘&’. De este modo, cuando llamamos a una función, lo que realmente
le pasamos son punteros a los argumentos que deseamos modificar. Veamos el ejemplo
anterior utilizando el paso de parámetros por referencia:

#include <stdio.h>

void modificar(int &variable);

main()
{
int i = 1;
printf("\ni=%d antes de llamar a la función modificar", i);
modificar(i);
printf("\ni=%d después de llamar a la función modificar", i);
return 0;
}
void modificar(int &variable)
{
printf("\nvariable = %d dentro de modificar", variable);
variable = 9;
printf("\nvariable = %d dentro de modificar", variable);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 10


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La salida de este ejemplo sería:

i=1 antes de llamar a la función modificar


variable = 1 dentro de modificar
variable = 9 dentro de modificar
i=9 después de llamar a la función modificar

Como se puede observar, el valor de i ha cambiado puesto que la función modificar ha


utilizado la dirección de memoria de esta variable en la sentencia de asignación variable =
9. Analicemos detenidamente este ejemplo. Lo primero que tenemos que tener en cuenta es
que la premisa de que en C++ todos los argumentos se pasan por valor sigue siendo cierta.
Lo que sucede es que en este caso estamos pasando el valor de la dirección de memoria de
la variable i y no el valor de su contenido. Para pasar la dirección de memoria de una
variable se utiliza el operador &. Al finalizar la función, el valor de dicha dirección
permanece igual y lo que se ha modificado es el contenido de esa dirección de memoria.

1.9. FUNCIONES RECURSIVAS.

Las funciones en C++ pueden ser recursivas, en otras palabras, pueden llamarse a sí
mismas directa o indirectamente.

La recursividad directa es el proceso mediante el que una función se llama a sí misma desde
el propio cuerpo de la función, mientras que la recursividad indirecta implica más de una
función.

Un proceso recursivo tiene que tener una condición de finalización, ya que de lo contrario
podría continuar infinitamente.

Un ejemplo típico de aplicación de la recursividad es el cálculo del factorial de un número


entero. Recordemos que el factorial de un número entero (n!) se calcula de la siguiente
manera:

n! = n * (n-1) * (n-2) * ... * 2 * 1

En principio, la solución a este problema podría realizarse sin tener que utilizar la
recursividad con el siguiente programa:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 11


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <stdio.h>

int factorial(int numero);

main()
{
int valor = 4;
int resultado;
resultado = factorial(valor);
printf("El factorial de %d es %d \n", valor, resultado);
return 0;
}

int factorial(int numero)


{
int i;
int devuelve = 1;
for(i = 1; i <= numero; i++)
{
devuelve = devuelve * i;
}
return devuelve;
}

Sin embargo, resulta más intuitivo dada la definición de número factorial utilizar una
función recursiva como la siguiente:

int factorial(int numero)


{
if(numero == 1)
return 1;
else
return (numero * factorial(numero-1));
}

En la función anterior, en el caso de que el argumento utilizado en la llamada sea 1, ésta


devuelve 1, y en caso contrario se calcula un producto que involucra a la variable numero y
una nueva llamada a la función cuyo argumento es menor en una unidad (numero -1).

El funcionamiento de una función recursiva se realiza almacenando las llamadas pendientes,


con sus argumentos, en la pila en tiempo de ejecución.

Veamos un ejemplo:

Si utilizamos el valor 4 como argumento de la función que calcula el factorial, es decir,


factorial(4), el proceso de llamadas será el siguiente:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 12


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Llamada # 1:
numero = 4
numero != 1 entonces ejecutamos la siguiente sentencia
return ( 4 * (realizamos la segunda llamada))
Llamada # 2:
numero = 3
numero != 1 entonces ejecutamos la siguiente sentencia
return ( 3 * (realizamos la tercera llamada))
Llamada # 3:
numero = 2
numero != 1 entonces ejecutamos la siguiente sentencia
return ( 2 * (realizamos la cuarta llamada))
Llamada # 4:
numero = 1
numero == 1 entonces se ejecuta la sentencia del if:
return 1
Fin Llamada # 4 -> DEVUELVE 1
return ( 2 * 1)
Fin Llamada # 3 -> DEVUELVE 2
return ( 3 * 2)
Fin Llamada # 2 -> DEVUELVE 6
return ( 4 * 6)
Fin Llamada #1 -> DEVUELVE 24

En toda función recursiva se debe identifica 2 momentos importante:

 CASO BASICO. En este momento la variable de recursión toma un valor inicial y no


es necesari establecer una llamada a la misma función.
 PROCESO RECURSIVO. En este momento es en el que se implementa un proceso
repetitivo por medio de una llamada a la misma función. Debemos tomar en cuenta que
el parámetro de la llamada recursiva debe ser menor que el parámetro de la función que
se define, de esta manera se evita procesos recursivos infinitos.

En el ejemplo del factorial se identifica estos mementos de la siguiente manera:

Caso básico:
Si numero=1 entoces factorial(1)=1
Proceso recursivo
si numero>1 entonces factorial(numero)= numero *factorial(numero-1)

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 13


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 2.
Programación Orientada a Objetos

Un paradigma de programación es una propuesta tecnológica adoptada por una comunidad


de programadores y desarrolladores cuyo núcleo central es incuestionable en cuanto que
únicamente trata de resolver uno o varios problemas claramente delimitados; la resolución
de estos problemas debe suponer consecuentemente un avance significativo en al menos un
parámetro que afecte a la ingeniería de software.

Un paradigma de programación representa un enfoque particular o filosofía para diseñar


soluciones. Los paradigmas difieren unos de otros, en los conceptos y la forma de abstraer
los elementos involucrados en un problema, así como en los pasos que integran su solución
del problema, en otras palabras, el cómputo.

Tiene una estrecha relación con la formalización de determinados lenguajes en su momento


de definición. Es un estilo de programación empleado.

Un paradigma de programación está delimitado en el tiempo en cuanto a aceptación y uso,


porque nuevos paradigmas aportan nuevas o mejores soluciones que la sustituyen parcial o
totalmente.

El paradigma de programación que actualmente es el más utilizado es la "orientación a


objetos" (OO). El núcleo central de este paradigma es la unión de datos y procesamiento en
una entidad llamada "objeto", relacionable a su vez con otras entidades "objeto".

Tradicionalmente, datos y procesamiento se han separado en áreas diferente del diseño y la


implementación de software. Esto provocó que grandes desarrollos tuvieran problemas de
fiabilidad, mantenimiento, adaptación a los cambios y escalabilidad. Con la OO y
características como el encapsulado, polimorfismo o la herencia, se permitió un avance
significativo en el desarrollo de software a cualquier escala de producción. La OO parece
estar ligada en sus orígenes con lenguajes como Lisp y Simula, aunque el primero que
acuñó el título de "programación orientada a objetos" fue Smalltalk.

La programación orientada a objetos, ha tomado las mejores ideas de la programación


estructurada y los ha combinado con varios conceptos nuevos y potentes que incitan a
contemplar las tareas de programación desde un nuevo punto de vista. La programación
orientada a objetos, permite descomponer mas fácilmente un problema en subgrupos de
partes relacionadas del problema. Entonces, utilizando el lenguaje se pueden traducir estos
subgrupos a unidades autocontenidas llamadas objetos.

El término Programación Orientada a Objetos (POO), hoy en día ampliamente utilizado, es


difícil de definir, ya que no es un concepto nuevo, sino que ha sido el desarrollo de técnicas
de programación desde principios de la década de los setenta, aunque sea en la década de
los noventa cuando ha aumentado su difusión, uso y popularidad. No obstante, se puede

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 14


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

definir POO como una técnica o estilo de programación que utiliza objetos como bloque
esencial de construcción.

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 objetos se denominan métodos y los datos se denominan miembros datos.

2.1 ORIGENES DE LA PROGRAMACION ORIENTADA A OBJETOS.

Al principio se empezaron a hacer lenguajes de alto nivel, orientados a procesos. Esa forma
de trabajar daba más importancia a los procesos que a los datos.

Entonces muchas personas se dieron cuenta de que los datos merecían mayor atención y así
aparecieron los lenguajes orientados a datos. Estos lenguajes tenían mucho cuidado con los
datos, pero los procesos eran muy sencillos o casi inexistentes. El problema era que cuando
había que cambiar la forma de los datos era necesario revisar todas las estructuras
anteriores.

De la síntesis entre la programación orientada a procesos y de la programación orientada a


datos nace la Programación Orientada a Objetos, un equilibrio entre las dos anteriores, que
cuida tanto datos como procesos y evita los problemas de acoplamiento de los otros
paradigmas.

Etapa 1. Lenguajes Ensambladores.

La unidad de programación es la instrucción, compuesta de un operador y los operandos. El


nivel de abstracción que se aplica es muy bajo.

Etapa 2. Lenguajes de Programación: Fortran, Algol, Cobol.

Los objetos y operaciones del mundo real se podían modelar mediante datos y estructuras
de control separadamente. En esta etapa el diseño del software se enfoca sobre la
representación del detalle procedimental y en función del lenguaje elegido. Conceptos
como: refinamiento progresivo, modularidad procedimientos y programación estructurada
son conceptos básicos que se utilizan en esta etapa. Existe mayor abstracción de datos.

Etapa 3.

Se introducen en esta etapa los conceptos de abstracción y ocultación de la información.

Etapa 4.

A partir de los años setenta se trabaja sobre una nueva clase de lenguajes de simulación y
sobre la construcción de prototipos tales como Simula-70 y basado en parte de éste, el

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 15


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Smalltalk. En estos lenguajes, la abstracción de datos tiene una gran importancia y los
problemas del mundo real se representan mediante objetos de datos a los cuales se les
añade el correspondiente conjunto de operaciones asociados a ellos. Términos como
Abstracción de datos, objeto, encapsulación entre otros, son conceptos básicos sobre la que
se fundamenta la POO.

2.2 CONCEPTOS DE LA PROGRAMACION ORIENTADA A OBJETOS.

Existen cuatro conceptos fundamentales dentro de la Programación Orientada a Objetos


que se relacionan entre sí y que nos permitirán tener las riendas de nuestro código:

Abstracción: proceso mental de extracción de las características esenciales de algo,


ignorando los detalles superfluos.

Encapsulación: proceso por el que se ocultan los detalles del soporte de las características
esenciales de una abstracción.

Modularización: proceso de descomposición de un sistema en un conjunto de módulos o


piezas independientes y cohesivos (con significado propio). Lo adecuado es conseguir los
mínimos acoplamientos.

Jerarquización: proceso de estructuración por el que se produce una organización


(jerarquía) de un conjunto de elementos en grados o niveles de responsabilidad,
incumbencia o composición entre otros.

La POO representa una metodología de programación que se basa en las siguientes


características:

1) Los diseñadores definen nuevas clases (o tipos) de objetos.


2) Los objetos poseen una serie de operaciones asociadas a ellos.
3) Las operaciones tienden a ser genéricas, es decir, operan sobre múltiples tipos de
datos.
4) Las clases o tipos de objetos comparten componentes comunes mediante
mecanismos de herencia.

Objeto:

Una estructura de datos y conjunto de procedimientos que operan sobre dicha


estructura. Una definición más completa de objeto es: una entidad de programa que
consiste en datos y todos aquellos procedimientos que pueden manipular aquellos
datos; el acceso a los datos de un objeto es solamente a través de estos
procedimientos, únicamente estos procedimientos pueden manipular, referenciar y/o
modificar estos datos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 16


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Para poder describir todos los objetos de un programa, conviene agrupar éstos en clases.

Clase:
Podemos considerar una clase como una colección de objetos que poseen
características y operaciones comunes. Una clase contiene toda la información
necesaria para crear nuevos objetos.

Encapsulación:
Es una técnica que permite localizar y ocultar los detalles de un objeto. La
encapsulación previene que un objeto sea manipulado por operaciones distintas de
las definidas. La encapsulación es como una caja negra que esconde los datos y
solamente permite acceder a ellos de forma controlada.

Las principales razones técnicas para la utilización de la encapsulación son:

1) Mantener a salvo los detalles de representación, si solamente nos interesa el


comportamiento del objeto.
2) Modificar y ajustar la representación a mejores soluciones algorítmicas o a nuevas
tecnologías de software.

Abstracción:
En el sentido mas general, una abstracción es una representación concisa de una
idea o de un objeto complicado. En un sentido mas especifico, la abstracción
localiza y oculta los detalles de un modelo o diseño para generar y manipular
objetos.

Una abstracción tiene un significado más general que la encapsulación, pudiendo hablar de
abstracción de datos en lugar de encapsulación de datos.

Como resumen de los 3 conceptos expuestos anteriormente podemos decir que:

1) Los objetos son encapsulaciones de abstracciones en la POO.


2) La unidad de encapsulación en la POO es el objeto.

Una clase es un tipo: Un objeto es una instancia de ese tipo. Además, la clase es un
concepto estático: una clase es un elemento reconocible en el texto del programa.

Un objeto es un concepto puramente dinámico, el cual pertenece, no al texto del programa,


sino a la memoria de la computadora, donde los objetos ocupan un espacio en tiempo de
ejecución una vez que haya sido creado.

La programación orientada a objetos, ha tomado las mejores ideas de la programación


estructurada y los ha combinado con varios conceptos nuevos y potentes que incitan a
contemplar las tareas de programación desde un nuevo punto de vista. La programación
orientada a objetos, permite descomponer mas fácilmente un problema en subgrupos de
partes relacionadas del problema. Entonces, utilizando el lenguaje se pueden traducir estos
subgrupos a unidades autocontenidas llamadas objetos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 17


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Objetos: Un objeto es una entidad lógica que contiene datos y un código que manipula
estos datos; el enlazado de código y de datos, de esta manera suele denominarse
encapsulación.

Cuando se define un objeto, se está creando implícitamente un nuevo tipo de datos.

Polimorfismo: Significa que un nombre se puede utilizar para especificar una clase
genérica de acciones.

Herencia: La herencia es un proceso mediante el cual un objeto puede adquirir las


propiedades de otro objeto.

2.3 PRESENTACION DE LAS CLASES Y LOS OBJETOS

Objeto: Un objeto es una entidad abstracta que tiene las características de un objeto real.

Los objetos se crean y eliminan durante la ejecución del programa, además interactúan con
otros objetos. Los objetos son construcciones de programación que se obtienen a partir de
entidades llamadas clases. La definición de una clase se conoce como instanciación de
clases.

Para crear un objeto, es preciso definir primero su forma general utilizando la palabra
reservada class. Una class es parecida a una estructura, es un tipo definido por el usuario
que determina las estructuras de datos y las operaciones asociadas con este tipo.

Las clases son como plantillas o modelos que describen como se construyen ciertos tipos de
objetos, cada vez que se construye un objeto de una clase se crea una instancia de esa clase,
por consiguiente; los objetos son instancias de clases.

Una clase es una colección de objetos similares y un objeto es una instancia de una
definición de una clase; una clase puede tener muchas instancias y cada una es un objeto
independiente.

Una clase es simplemente un modelo que se utiliza para describir uno o mas objetos del
mismo tipo.

Así, por ejemplo sea una clase ventana, un tipo de dato, que contenga los miembros dato:

posx, posy
tipo_ventana
tipo_borde
color_ventana

y unas funciones miembro:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 18


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

mover_horizontal
mover_vertical

Un objeto de la clase ventana, es una ventana concreta (una instancia de la clase) cuyos
datos tienen por valores:

Posx x
posy y
tipo_ventana desplegable
tipo_borde linea doble
color_ventana amarillo

2.3.1 DEFINICIÓN DE UNA CLASE.

Las clases son estructuras que contienen no sólo declaraciones de datos, sino también
declaraciones de funciones. Las funciones se conocen como funciones miembro, e indican
qué tipos de cosas puede hacer una clase. La palabra reservada class introduce una
declaración de clase.

2.3.2 IDENTIFICADORES DE CLASE.

La longitud máxima para un identificador de clase es 32 caracteres. Una convensión que se


adopta en todas las clases de borland es utilizar nombres que comiencen con una letra
mayúscula para denotar clases y estructuras globales.

2.3.2.1 CUERPO DE UNA CLASE.

La forma general de la declaración de una clase es:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 19


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Nombre_de_la_clase{
private:
datos y funciones privados

public:
datos y funciones publicas

}lista de objetos;
Una clase puede contener tanto partes públicas como partes privadas, por defecto, todos los
elementos que se definen en la clase son privados; esto significa que no pueden acceder a
ellas ninguna función que no sea miembro de la clase.

Class Counter{
long count; // variable privada , variable miembro de la clase

Public:
void SetValue(long); // Funciones públicas, funciones miembro de la
clase
long GetValue();
};

La variable long count, no está disponible o no se puede usar por otras funciones que no
están declaradas en la clase, por lo que tratar de hacer esto es erróneo:

void main()
{
count = 3.111;
}

Una clase puede tener tantas variables como necesite. Estas pueden ser de cualquier tipo,
incluyendo otras clases, apuntadores a objetos de clases e incluso apuntadores a objetos
dinámicamente asignados.

Las funciones miembro SetValue(long) y GetValue(). Solo están declaradas dentro de la


clase, la definición de estas funciones sería así:

void Counter::SetValue(long value)


{
count = value;
}
long Counter::GetValue()
{
return count;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 20


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.3.3 USO DE UNA CLASE.

Ya que se ha definido la clase, se debe definir un objeto con ella. Las variables de una clase
se definen de igual manera que como se definen las variables de tipo estructura.

Para el ejemplo de la clase anterior, si quiere declarar un objeto Gente de tipo Counter, lo
podría hacer asi:

Class Counter
{
.
.
public:
.
.
}Gente;

O la declaración la podría hacer de la siguiente forma:

Counter Gente;

En algunos lenguajes orientados a objetos, Smalltalk en particular, la definición de una


variable de clase se denomina instanciación de la clase.

Una instanciación es simplemente una instancia de una clase en la forma de una variable
específica.

Las variables instanciadas a partir de clases son objetos.

El objeto Gente se podría usar así en un programa:

void main()
{
Counter Gente; // Declaración de un objeto
Gente.SetValue(1000); // Invocación a función miembro de Counter
long value = GetValue(); // Invocación a función miembro de Counter
}

La iniciación se tiene que hacer a través de sus funciones miembro, por lo que hacer lo
siguiente sería un error.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 21


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
Counter Gente;
Gente = 1000; // error, la variable no está disponible en la función main()
long value = GetValue();
}

El código anterior no hace mucho, pero ilustra 2 aspectos importantes:

La declaración de un objeto dentro de una función y la invocación de funciones miembro


de un objeto.

En otro ejemplo, ésta clase define un tipo llamado cola, que se utiliza para crear un objeto
de tipo cola.

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
void iniciar(void);
void ponent(int i);

int quitaent(void);
};

Cuando llega el momento de codificar realmente una función que es miembro de una clase,
es preciso decir al compilador a que clase pertenece la función, calificando el nombre de la
función con el nombre de la clase del cual es miembro. p.e.

void cola :: ponent(int i)


{
if(posfin>=100)
{
cout<<"la cola esta llena ";
return;
}
posfin++;
c[posfin] = i;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 22


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El :: se llama operador de resolución de ámbito; indica al compilador que la función


ponent(int i) pertenece a la clase cola, o dicho de otra manera, ponent(int i) está dentro del
ámbito de cola.

Para llamar a una función miembro desde una parte del programa que no sea parte de la
clase, se debe utilizar el nombre del objeto y el operador punto. p.e.

Cola a, b; // se crean 2 objetos tipo cola.

a.iniciar(); // llama a la función iniciar para el objeto a.

Consideremos el siguiente ejemplo, de un programa en C++, aunque en una aplicación real


la declaración de las clases debe estar contenida en un archivo de cabecera.

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
void iniciar(void);
void ponent(int i);
int quitaent(void);
};

main(void)
{
cola a, b;
a.iniciar();
b.iniciar();
a.ponent(15);
b.ponent(39);
a.ponent(55);
b.ponent(19);
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
return 0;
}

void cola::iniciar()
{
posprin=posfin=0;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 23


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void cola::ponent(int i)
{
if(posfin==0)
{
cout<<"la cola esta llena ";
return;
}
posfin++;
c[posfin] = i;
}

int cola::quitaent(void)
{
if(posfin==posprin)
{
cout<<"la cola está vacía";
return 0;
}
posprin++;
return c[posprin];
}

2.4 ACCESO A UNA CLASE.

La tarea de una clase consiste en ocultar la mayor cantidad de información posible. Por lo
tanto es necesario imponer ciertas restricciones a la forma en que se puede manipular una
clase. Existen 3 tipos de usuario de una clase:

1.- La clase misma.


2.- Usuarios genéricos.
3.- Clases derivadas.

Cada tipo de usuarios tiene privilegios de acceso asociados a una palabra clave:

1.- Private.
2.- Public.
3.- Protected.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 24


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Ejemplo:

class controlAcceso
{
int a;
public:
int b;
int fi(int a);
protected:
int c;
float C1(float t);
};

Cualquier declaración que aparezca antes de cualquiera de las tres palabras clave, por
default es private; así, int a; es private.

2.4.1 MIEMBROS DE LA CLASE PRIVATE.

Los miembros de la clase private tienen el mas estricto control de acceso. Solo la clase
misma puede tener acceso a un miembro private. En este ejemplo nadie puede usar la clase
ya que todo es private.

Class Privada
{
long valor;

void F1();
void F2();
};

void main()
{
privada objeto1; // Se crea objeto1 de clase privada.
long L = &objeto.valor; // acceso no valido por ser private.
objeto1.F1(); // acceso no valido por ser private.
objeto1.F2(); // acceso no valido por ser private.
}

Para poder tener acceso necesitaría que las funciones miembro fueran declaradas en la
sección public.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 25


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.4.2 MIEMBROS DE LA CLASE PUBLIC:

Para utilizar un objeto de una clase, usted debe tener acceso a datos miembro, a funciones
miembro o a ambos. Para hacer que algunos datos o funciones sean accesibles, se declaran
en la sección public.

class Ej_public
{
public:
int variable;
void función1();
};

void Ej_public::función1(){}

void main()
{
Ej_public Objeto2;
int i = Objeto2.variable;
Objeto2.función1();
}

Cualquier cosa que se declara en la sección public, hace posible el acceso ilimitado a
cualquier persona.

2.4.3 MIEMBROS DE LA CLASE PROTECTED.

Cuando se define una clase que se utiliza subsiguientemente como clase de base para otras
clases, se puede hacer que los miembros estén accesibles solo para funciones de las clases
derivadas mediante el uso de la palabra clave protected.

Considere una jerarquía de objetos como se ilustra a continuación:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 26


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La jerarquía de clase se puede expresar con código así:

class A
{
Protected:
int valor_A;
};

class B
{
public:
void funB();
};

class C
{
public:
void funC();
};

La propiedad de ser protected se extiende indefinidamente hacia abajo en un árbol de


herencia, en tanto que se declare que las clases derivadas tengan clases de base public. Por
ejemplo el código siguiente es aceptable.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 27


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void funB()
{
valor_A = 0;
}

void funC()
{
valor_A = 1000;
}

2.5. APUNTADORES COMO MIEMBROS DE DATOS.

Los miembros de datos pueden ser también apuntadores. Los apuntadores no se pueden
inicializar dentro de la declaración de una clase. Si un miembro de datos apunta a un tipo de
clase, el apuntador no se iniciliza, ni las construcciones son llamadas de manera automática.

Ejemplo.

class Segunda
{
int id;
public:
Primera* Object;
Segunda();
Int getnom() { return id; }
};

Aquí, el miembro se declara para apuntar a un elemento de otra clase llamada primera. En
la construcción de la clase segunda, el espacio de almacenamiento se asigna al objeto
apuntador, pero el apuntador se deja sin inicializar.

2.5.1 APUNTADORES A MIEMBROS DE DATOS DE CLASES.

Las clases no son objetos, pero aveces puede utilizarlas como si lo fueran. Un ejemplo es la
declaración de un apuntador a un miembro de clase.

class Ejemplo
{
public:
int valor;
int identificador;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 28


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void SetValue(Ejemplo& Objeto)


{
int Ejemplo::*ip = & Ejemplo::valor;
Objeto.*ip = 3;
}

void main()
{
Ejemplo Objeto1;
Ejemplo Objeto2;
SetValue(Objeto1);
SetValue(Objeto2);
}

La función SetValue() tiene la declaración inusual:

Int Ejemplo::*ip = & Ejemplo::valor;

Esta instrucción declara la variable ip que apunta a un valor de miembro de datos int en un
objeto de clase Ejemplo sin indicar un objeto especifico.

2.6. CONSTRUCTORES.

Un constructor es una función especial que es miembro de esa clase y que tiene el mismo
nombre de la clase.

Es muy frecuente que una cierta parte de un objeto necesite una iniciación antes de que
pueda ser utilizada; como el requisito de iniciación es tan frecuente C++ permite que los
objetos se den a sí mismos valores iniciales cuando se crean. Esta iniciación
automáticamente se lleva a cabo mediante el uso de una función de construcción o
constructor.

Por ejemplo este es el aspecto que tiene la clase cola cuando se modifica para utilizar las
iniciaciones:

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
cola(void); // este es el constructor de la clase cola
void ponent(int i);
int quitaent(void);
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 29


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Obsérvese que no se especifica un tipo de dato proporcionado para el constructor cola(). En


C++, los constructores pueden proporcionar valores.

La función cola() se codifica de la siguiente manera:

cola::cola(void)
{
posfin=posprin=0;
cout<<"la cola ya tiene valores iniciales \n";
}

La función de construcción de un objeto se invoca cuando se crea el objeto. Esto significa


que se invoca cuando se ejecuta la declaración del objeto. Además, para los objetos locales,
el constructor se invoca cada vez que se llega a la declaración del objeto.

Como lo dice el nombre, un constructor es una función que se utiliza para construir un
objeto de una clase dada; esto puede implicar la presencia de diferentes escenarios.

1.- Creación de objetos con iniciación definida.


2.- Creación de objetos con iniciación especifica.
3.- Creación de objetos copiando otro objeto.

Cada uno de estos procesos implica un tipo diferente de constructor. Un constructor tiene el
nombre de la clase a la que pertenece.

Un sub objeto es un objeto de clase que se declara dentro de otra clase. Cuando se tiene una
instancia en una clase, su constructor debe crear un objeto de esa clase. Si la clase tiene sub
objetos declarados en ella, el constructor tiene que invocar los constructores de estos
objetos. Considere el ejemplo siguiente.

class counter
{
int value;
public:
Counter() { value = 0; }
};

class Example
{
int value;
public:
Counter cars;
Example() { value = 0; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 30


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
Example e;
}

Cuando se crea el objeto e en main(), se llama al constructor de la clase Example; en este


caso, la función Example::Example() antes de ejecutar su cuerpo, invoca al constructor
Counter::Counter() del sub objeto cars. Cuando se completa este constructor, se ejecuta el
cuerpo de Example::Example().

2.6.1 CONSTRUCTORES PRIVATE.

Obsérvese que el constructor anterior aparece en la sección public de la clase; este no es un


requisito, pero normalmente es el caso.

Un constructor private, impediría que los usuarios genéricos crearan objetos a partir de esa
clase y forzarán el cumplimiento de una de las condiciones siguientes antes de que se pueda
crear un objeto.

1. Un miembro estático de la clase invoca al constructor.


2. Una clase friend de esa clase invoca al constructor.
3. Un objeto existente de la clase tiene una función miembro que crea nuevos
objetos invocando al constructor.

2.6.2 CONSTRUCTORES CON ARGUMENTOS.

La función básica de un constructor consiste en inicializar un objeto antes de usarlo.

Counter(long);

Counter::Counter(long value)
{
count = value;
}

void main()
{
Counter object(5);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 31


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Observe los paréntesis después del nombre de la variable, que hacen que la definición del
objeto se asemeje a una llamada a función. La definición del objeto es en realidad una
llamada a función con argumentos.

Suponga que desea crear una clase counter que sea lo suficientemente flexible para aceptar
cualquier tipo de inicialización, utilizando elementos float, long, int, cadena o incluso
ningún argumento. Estas son las construcciones que se deben declarar.

class Counter
{
public:
Counter(int = 0);
Counter(long);
Counter(double);
Counter(char *);
};

// declaración de constructores.
Counter::Counter(long val_inic)
{
count = val_inic;
}

Counter::Counter(double val_inic)
{
count = val_inic;
}

Counter::Counter(char* val_inic)
{
count = atol(val_inic);
}

// uso de los constructores.


void main()
{
Counter Object(“5”); // Utilizando constructor char*
Counter Object1(5); // Utilizando constructor int
Counter Object2(5L); // Utilizando constructor long
Counter Object3(5.0); // Utilizando constructor double
Counter Object4(); // Utilizando constructor por omisión
}

El compilador puede determinar automáticamente a que constructor llamar en cada caso


examinando los argumentos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 32


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.6.3 CONSTRUCTORES PARA COPIAR OBJETOS.

Cuando se crea un objeto, a menudo no se desea inicializar ningún valor de manera


específica; simplemente se desea que un objeto “sea como otro”. Esto implica hacer una
copia de un objeto preexistente, lo cual requiere un tipo especial de construcción, llamada
en general: constructor de copia. Ejemplo.

class Counter
{
.
.
.
public:
Counter(Counter&);
.
.
};

Counter::Counter(Counter &referencia)
{
count = referencia.count;
}

void main()
{
Counter Object(5); // Constructor entero
Counter Object1 = Object; // Constructor de copia
}

2.7 DESTRUCTORES.

Los destructores entran en la misma categoría que los constructores. Se utilizan para
realizar ciertas operaciones que son necesarias cuando ya no se utiliza un objeto como es la
liberación de memoria.

Existen algunas diferencias importantes entre los constructores y los destructores:

1.- Los destructores pueden ser virtuales, los constructores NO.


2.- A los destructores no se les puede mandar argumentos.
3.- Sólo se puede declarar un destructor para una clase dada.

El destructor se nombra como la clase pero este va precedido de un tilde (~).

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 33


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Se podría escribir una clase que se encargue de manejar todas las gráficas generadas por un
programa de la siguiente manera:

class Graphics
{
public:
Graphics();
~Graphics();
void DrawCircle(int x, int y, int radio);
void DrawDot(int x, int y);
};

El destructor se utiliza para cerrar el dispositivo gráfico y rechazar cualquier espacio de


memoria asignado al objeto.

Por ejemplo vea la clase cola con su constructor y destructor (en el ejemplo de la clase cola
no es necesario un destructor, pero en este caso se pone para ejemplificar su uso).

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
cola(void); // este es el constructor de la clase cola
~cola(void); // este es el destructor de la clase cola
void ponent(int i);
int quitaent(void);
};

// Función de Construcción
cola::cola(void)
{
posfin=0;
posprin=0;
}

// Función de destrucción.
cola::~cola(void)
{
cout<<"la cola ha sido destruida \n";
}

Veamos como funcionan los constructores y destructores en la nueva versión del programa
que crea una cola.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 34


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

# include <iostream.h>
class cola
{
int c[100];
int posfin, posprin;
public:
cola(void); // este es el constructor de la clase cola
~cola(void); // este es el destructor de la clase cola
void ponent(int i);
int quitaent(void);
};

main(void)
{
cola a, b;
a.ponent(15);
b.ponent(39);
a.ponent(55);
b.ponent(19);
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
cout<<a.quitaent() << " ";
cout<<b.quitaent() << " ";
return 0;
}
// Función de Construcción
cola::cola(void)
{
posfin=0;
posprin=0;
cout<<"La cola ya tiene valores iniciales \n"
}
// Función de destrucción.
cola::~cola(void)
{
cout<<"La cola ha sido destruida \n";
}
void cola::ponent(int i)
{
if(posfin>=100)
{
cout<<"la cola esta llena ";
return;
}
posfin++;
c[posfin] = i;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 35


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int cola::quitaent(void)
{
if(posfin==posprin)
{
cout<<"la cola está vacía";
return 0;
}
posprin++;
return c[posprin];
}

Este programa da como resultado lo siguiente:

La cola ya tiene valores iniciales.


La cola ya tiene valores iniciales.
15 39
55 19
La cola ha sido destruida.
La cola ha sido destruida.

2.8 CLASES AMIGAS (Palabra reservada friend)

A veces se necesitan 2 clases que son tan conceptualmente cercanas que usted desearía que
una de ellas tuviera acceso irrestricto a los miembros de la otra. Considere la implantación
de una lista asociada: necesita una clase que represente nodos individuales, y una que se
encargue de la lista misma. El acceso a los miembros de la lista es a través del manejador
de la misma, pero el manejador debe tener acceso absoluto a los miembros de la clase o una
función. Una clase que no ha sido declarada aún se puede definir como friend de esta
manera:

class Node
{
friend class ObjectList;
int value;
Node* Predecesor;
Node* Sucesor;
public:
void value(int i)
{
value = i;
}

};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 36


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class ObjectList
{
Node* head;
Node* tail;
Node* current;
public:
void InsertNode(Node * ) {}
void DeleteNode(Node *) {}
int CurrentObject(Node* node) { return node->value;}
};

2.8.1 FUNCIONES AMIGAS.

Es posible que una función de una clase que no sea un miembro tenga acceso a las partes
privadas de esa clase, declarando que se trata de un friend (amigo) de esa clase. Por
ejemplo amg() se declara como friend de la class C1

Class C1
{
.
.
.
public:
friend void amg(void);
.
.
.
};

Como se puede ver, la palabra reservada friend precede a toda la declaración de la función,
que es lo que se hace en general.

La razón por la cual se permite en C++ las funciones friend es la de resolver situaciones en
las cuales dos clases deban compartir una misma función, para así aumentar la eficiencia.
Para ver un ejemplo, consideremos un programa que defina dos clases llamadas linea y
recuadro. La clase linea contiene todos los datos y código necesarios para dibujar una línea
horizontal discontinua de cualquier longitud, empezando en la coordenada X, Y que se
indique y utilizando un color especificado, La clase recuadro contiene todo el código y los
datos necesarios para dibujar un recuadro en las coordenadas especificadas para la esquina
superior izquierda y para la esquina inferior derecha, y con el color que se indique. Las dos
clases tienen la misma función mismo_color() para determinar si una línea y un recuadro
están pintados del mismo color. Las clases se declaran según se muestra a continuación:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 37


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class linea;

class recuadro
{
int color;
int xsup, ysup;
int xinf, yinf;
public:
friend int mismo_color(linea l, recuadro b);
void pon_color(int c);
void definir_recuadro(int x1, int y1, int x2, int y2);
void mostrar_recuadro(void);
};

class linea
{
int color;
int xinicial, yinicial;
int longitud;
public:
friend int mismo_color(linea l, recuadro b);
void pon_color(int c);
void definir_linea(int x, int y, int l);
void mostrar_linea();
};

La función mismo_color(), que no es miembro de ninguna de ellas pero es friend de ambas,


proporciona un valor verdadero si tanto el objeto línea como el objeto recuadro, que son sus
argumentos, se dibujan del mismo color; en caso contrario, proporciona un valor nulo. La
función mismo_color se muestra a continuación:

Int mismo_color(linea l, recuadro b)


{
if(l.color == b.color)
return 1;
return 0;
}

También puede declarar una función no miembro como friend antes que el identificador de
la función esté en el campo de acción. Por ejemplo.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 38


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Node
{
friend int GetObject(Node*);
int value;
Node* Predecesor;
Node* Sucesor;

public:
void value(int i){ value = i; }
};

int GetObject(Node* n)
{
return n->value;
}

2.8.2 PROPIEDADES DE LA PALABRA RESERVADA friend.

Las funciones y clases declaradas friend para otras clases gozan de privilegios especiales.
Si la función FUN0() es un elemento friend de la clase B y la clase B se deriva de la clase
A. FUN0(), tiene acceso también a los miembros de datos de las clases A, B, y C:

class A
{
friend class FRIEND;
int a1;
protected:
int a2;
public:
int a3;
};

class B
{
int b1;
protected:
friend class FRIEND;
int b2;
public:
int a3;
};

La clase friend puede tener acceso a todos los miembros de datos de C.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 39


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class C
{
int c1;
protected:
int c2;
public:
friend class FRIEND;
int c3;
};

2.9 HERENCIA

La herencia es uno de los rasgos fundamentales de un lenguaje de programación orientado a


objetos. En C++, la herencia se basa en permitir que una clase contenga a otra clase en su
declaración; supongamos una clase Figura:

Class Figura{
.
.
public:
.
.
};

Una clase derivada Figura_Circulo se declara así.

Class Figura_Circulo:public Figura


{
public:
.
private:
double x_centro, y_centr;
double radio;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 40


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La declaración general de la herencia es la que se muestra a continuación:

Class Nombre_de_la_clase_nueva : acceso clase_heredada


{
.
.
.
};

Aquí acceso es opcional, sin embargo, si está presente tiene que ser public, private o
protected.

El uso de public significa que todos los elementos public del antecesor también serán public
para la clase que lo hereda.

El siguiente ejemplo muestra 2 clases donde la segunda de ellas hereda las propiedades de
la primera.

class Box
{
public:
int width, height;
void SetWidth(int w) { width = w; }
void SetHeight(int h) { height = h; }
};

class ColoredBox:public Box


{
public:
int color;
void Setcolor(int c) { color = c; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 41


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

La clase Box recibe el nombre de clase base de la clase ColoredBox. Que a su vez recibe el
nombre de clase derivada. La clase Colored Box se declara solo con una función, pero
también hereda 2 funciones y 2 variables de su clase base. Así, se puede crear el código
siguiente:

ColoredBox Cb; // se crea una instancia de ColoredBox

void main()
{
Cb.Setcolor(5); // función miembro de ColoredBox.
Cb.SetWidth(30); // función heredada.
Cb.setHeight(50); // función heredada.
}

Observe como las funciones heredadas se utilizan exactamente como si fueran miembro.

2.9.1 LIMITACIONES DE LA HERENCIA.

Cómo y cuándo se deriva una clase de otra es puramente decisión del programador. Esto
puede parecer obvio, pero es una limitación. El diseñador de un programa debe decidir al
momento de la compilación quien hereda qué, de quién, cómo y cuándo se lleva a cabo la
herencia.

2.9.2 QUE NO SE PUEDE HEREDAR.

Tal y como en la vida real, en C++ no todo se puede transmitir a través de la herencia. Esto
se puede considerar en un principio como una desventaja o limitación, pero en realidad solo
algunos casos especiales inconsistentes por definición con la herencia:

1.- Constructores.
2.- Destructores.
3.- Nuevos operadores definidos por el usuario.
4.- Relaciones friend.

El constructor de una clase de base no puede ser invocado de manera explícita en una clase
derivada como otras funciones heredadas. Considere el código siguiente:

class Parent
{
int value;
public:
Continua…
Parent(){ value = 0; }
Parent(int v){ value = 0; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 42


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Child:public Parent


{
int total;
public:
Child(int t) { total = t; }
void SetTotal(int t);
};

void Child::SetTotal(int t)
{
Parent::Parent(i); // Esto no se puede hacer, ya que el constructor de la
// clase no es heredado como otras funciones.
Total = t;
}

De manera análoga, los destructores están diseñados para ser invocados automáticamente
cuando un objeto sale del campo de acción.

La relación friend no es heredada. Esto es similar a la vida real; los amigos de sus padres no
son automáticamente amigos suyos.

2.9.3 HERENCIA MULTIPLE.

Una clase puede heredar los atributos de dos o más clases. Para lograr esto, se utiliza una
lista de herencia separada mediante comas en la lista de clases base de la clase derivada. La
forma General es:

Class Nombre_clase_derivada : lista de clases base


{
.
.
.
};

Por ejemplo en este programa Z hereda tanto a X como a Y.

# include <iostream.h>
class X
{
protected:
int a;
public:
void hacer_a(int i);
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 43


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class Y
{
protected:
int b;
public:
void hacer_b(int i);
};

// Z hereda tanto a X como a Y

class Z : public X, public Y


{
public:
hacer_ab(void);
};
void X::hacer_a(int i)
{
a = i;
}
void Y::hacer_b(int i)
{
b = i;
}
int Z::hacer_ab(void)
{
return a*b;
}

main(void)
{
Z var;
var.hacer_a(10);
var.hacer_b(25);
cout << var.hacer_ab();
return 0;
}

En este ejemplo, Z tiene acceso a las partes public y protected tanto de X como de Y.
Remarcando, una clase puede tener muchos padres y heredar propiedades de cada una de
sus clases base. Considere crear una clase MesaRedonda, que no solo tenga las propiedades
de las mesas, sino también la característica geométrica de ser redonda.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 44


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <stdio.h>
class Circle
{
float radio;
public:
Circle(float r){ radio = r; }
Float Area(){ return radio*radio*3.1416; }
};

class Mesa
{
float height;
public:
Mesa(float h) { height = h; }
float Height() { return height; }
};

class MesaRedonda:public Mesa, public Circle


{
int color;
public:
MesaRedonda(float h, float r, int c);
int Color() { return color; }
};

MesaRedonda::MesaRedonda(float h, float r, int c): Circle(r),Mesa(h)


{
color = c;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 45


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
MesaRedonda Mesa1(15.0, 3.0, 5);
printf("\n Las propiedades de la Mesa son:");
printf("\n Altura = %f ", Mesa.Height());
printf("\n Area = %f ", Mesa.Area());
printf("\n Color = %d ", Mesa.Color());
}

La función main() invoca las tres funciones miembro MesaRedonda::Height(),


MesaRedonda::Area() y MesaRedonda::Color(). Todo sin indicar cuales son funciones
heredadas y cuales no.

2.9.4 USO DE CLASES DE BASE VIRTUAL.

Las clases de base virtual se utilizan sólo en el contexto de la herencia múltiple. Dada la
complejidad de relaciones que pueden surgir en un árbol de herencia construido en torno a
la herencia múltiple, existen situaciones en las que el programador necesita tener cierto
nivel de control sobre la forma en que se heredan las clases de base. Considere el árbol de
herencia de la siguiente figura.

La clase D tiene a A como clase de base. El problema es que hay dos clases A diferentes
que aparecen como clases de base de D, cada una con datos propios.

Esto se ejemplifica con el siguiente código.

class A
{
public:
int value;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 46


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class B : public A{};


class C : public A{};
class D : public B, public C
{
public:
int value()
{
return value;
}
};

El valor miembro de acceso a la instrucción en D es ambiguo. Borland C++ genera error.

Tener múltiples copias de la misma clase de base en árbol de herencia no sólo es confuso,
sino que puede ser un desperdicio de espacio de almacenamiento.

Declarar una base virtual resuelve el problema. Obliga al compilador a admitir sólo una
copia de la clase de base dada en la declaración de una clase derivada. Por lo tanto el
ejemplo anterior lo podemos corregir de la siguiente manera:

class B : public virtual A{};


class C : public virtual A{};
class D : public B, public C
{
public:
int value()
{
return value;
}
};

y el árbol de herencia quedaría como realmente lo deseamos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 47


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.10 SOBRECARGA.

Una de las maneras que tiene el C++ de llegar al polimorfismo es a través de la sobrecarga
de funciones. En C++ , dos o mas funciones pueden compartir un nombre, siempre y
cuando en la declaración, sus parámetros sean diferentes.

Sobrecarga se refiere a la práctica de cargar una función con más de un significado.


Básicamente, el término expresa que se cargan uno o más identificadores de función sobre
un identificador previo.

2.10.1 PORQUE USAR LA SOBRECARGA.

La sobrecarga no es un concepto nuevo en los lenguajes de programación, por ejemplo el


operador = está sobrecargado en muchos lenguajes de alto nivel y se utilizan en
instrucciones de asignación y en expresiones condicionales como:

a = b;
if( a = b)

La sobrecarga otorga flexibilidad, permite a las personas utilizar código con menos
esfuerzo, ya que extiende operaciones que son conceptualmente similares en naturaleza.

2.10.2 SOBRECARGA DE FUNCIONES.

Las funciones sobrecargadas se distinguen por el número y tipo de sus argumentos.

El tipo de retorno no se utiliza para distinguir funciones sobrecargadas, por lo tanto las
funciones:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 48


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void Muestra(int q);


long Muestra(int q);

No son distinguibles y producen un error del compilador.

Cualquier nombre de función puede ser sobrecargada en C++, pero la sobrecarga solo
funciona dentro de un campo de acción dado.

Cuando se declara en una clase más de una función miembro con el mismo nombre, se dice
que el nombre de la función está sobrecargado en esa clase, y su campo de acción será en el
ámbito de esa clase.

class Ejemplo
{
int value;
public:
void value(int v) { value = v; }
int value() { return value; }
};
void main()
{
Ejemplo Ee;
Ee.value(3);
Int i = Ee.value();
}

Este código demuestra que la clase Ejemplo tiene 2 funciones sobrecargadas: una función
para escribir y una para leer una variable.

Las funciones sobrecargadas necesitan diferir en una u otra o en las dos formas siguientes:

1.- Las funciones deben contener un número de argumentos diferente.


2.- Cuando menos uno de los argumentos debe ser diferente.

Considere el siguiente programa en el cual la función al_cuadrado se sobrecarga 3 veces.

# include<iostream.h>
int al_cuadrado(int i);
double al_cuadrado(double d);
long al_cuadrado(long l);
main(void)
{
cout << al_cuadrado(10) <<" \n";
cout << al_cuadrado(1.25) <<" \n";
cout << al_cuadrado(9L) <<" \n";
return 0;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 49


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int al_cuadrado(int i)
{
cout<<" función al_cuadrado con parámetro entero"
return i*i;
}

double al_cuadrado(double d)
{
cout<<" función al_cuadrado con parámetro doble"
return d*d;
}

long al_cuadrado(long l)
{
cout<<" función al_cuadrado con parámetro largo"
return l*l;
}

La ventaja de sobrecargar las funciones es que permite acceder a conjuntos de funciones


que están relacionadas utilizando un solo nombre. En el programa anterior se crean 3
funciones similares que se llaman, al_cuadrado(), y cada una de las cuales regresa el
cuadrado de su argumento; en cierto sentido, la sobrecarga de funciones permite crear un
nombre genérico para alguna operación, y el compilador resuelve que función es la
adecuada para llevar a cabo la operación.

Así, al_cuadrado(), representa la acción general que se realiza; el programador solo necesita
recordar la acción general que se lleva a cabo, por lo tanto al aplicar el polimorfismo se han
reducido a una las 3 cosas que había que recordar. Aunque este ejemplo es bastante trivial,
si expande el concepto se puede ver que el polimorfismo puede ayudarnos a entender
programas muy complejos.

Para sobrecargar la función de construcción de una clase, solo hay que declarar las
diferentes formas que tiene que adoptar y hay que definir su acción con respecto a esas
formas. Por ejemplo el programa siguiente declara una clase llamada temporizador, que se
comporta como un temporizador descendente. Cuando se crea un objeto del tipo
temporizador, se le da un valor inicial de la hora. Cuando se invoca a la función ejecutar(),
el temporizador cuenta hasta llegar a cero, y hace sonar el timbre. En ese ejemplo, se ha
sobrecargado el constructor para especificar la hora como un entero, como una cadena, o
como dos enteros que especifican los minutos y los segundos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 50


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

# include <iostream.h>
# include <stdlib.h>
# include <time.h>
class temporizador
{
int segundos;
public:
// Se especifican los segundos como una cadena.
temporizador(char *t) {segundos = atoi(t);}
// Se especifican los segundos como un entero
temporizador(int t) {segundos = t;}
// Se especifica la hora en minutos y segundos
temporizador(int min, int seg) {segundos = min* 60 + seg; }
void ejecutar(void);
};

void temporizador::ejecutar(void)
{
clock_t t1, t2;
t1 = t2 = clock()/CLK_TCK;
while(segundos)
{
if(t1/CLK_TCK+1 <= (t2=clock()) /CLK_TCK)
{
segundos --;
t1 = t2;
}
}
cout << "\a"; // toca el timbre
}

main(void)
{
temporizador a(10), b("20"), c(1, 10);
a.ejecutar(); // cuenta 10 segundos
b.ejecutar(); // cuenta 20 segundos
c.ejecutar(); //cuenta 1 minuto, 10 segundos
return 0;
}

Como se puede ver, cuando a, b, y c se crean dentro de main(), se les dan valores iniciales
utilizando los tres métodos diferentes que admiten las funciones de construcción
sobrecargadas.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 51


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.10.3 CONSTRUCTORES SOBRECARGADOS.

Uno de los usos más comunes de la sobrecarga de funciones es con los constructores. La
razón es que cuando se instancía una clase, se deben conservar las cosas lo más flexibles
que sea posible; de modo que los usuarios pueden realizar diferentes clases de instancias.

Considere una clase ventana desplegable en una interfaz gráfica de usuario.

PopupWindow Window; // Genera una ventana con parámetros por


// omisión.
PopupWindow Window_1(x, y); // Genera una ventana con coordenadas
// específicas.
PopupWindow Window_2(x, y, width, Height); // Genera una ventana con
// dimensiones controladas.
PopupWindow Window_3 = Window_2; // Genera una ventana igual a la
// anterior.

La implantación de esta clase podría parecerse al siguiente código.

class PopupWindow
{
Int x, y, Width, Height;
public:
PopupWindow();
PopupWindow(int, int);
PopupWindow(int, int, int, int);
PopupWindow(PopupWindow&);
};

PopupWindow:: PopupWindow()
{
x = y = 100;
Widht = Heigth = 100;
}

PopupWindow:: PopupWindow(int px, int py)


{
x = px;
y = py;
Widht = Heigth = 100;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 52


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

PopupWindow:: PopupWindow(int px,int py, int w, ,int h)


{
x = px;
y = py;
Widht = w;
Heigth = h;
}

PopupWindow:: PopupWindow(PopupWindow& pw)


{
x = pw.x;
y = pw.y;
Widht = pw.Widht;
Heigth = pw.Height;
}

La clase utiliza cuatro funciones sobrecargadas que realizan el trabajo.

Con constructores sobrecargados, usted puede permitir que el usuario especifique qué
variables han de ser inicializadas de manera explícita y cuales deben asumir valores
definidos.

2.10.4 SOBRECARGA DE OPERADORES.

Otra forma en que se logra el polimorfismo en C++ es mediante la sobrecarga de


operadores. En general se puede sobrecargar cualquiera de los operadores de C++
definiendo lo que significa con respecto a una cierta clase.

Aunque los operadores están asociados comúnmente con operaciones matemáticas o


lógicas, simplemente son una notación alternativa para una llamada a una función

La sobrecarga de operadores se utiliza en otros lenguajes de programación, pero sin un


nombre especial. En algunos lenguajes como Pascal, es posible hacer lo siguiente:

StructureA := structureB + structureC;

Lo que da lugar a una adición byte por byte de las estructuras b y c que se copiarán en la
estructura a. Esta sintaxis implica que el operador de adición está sobrecargado para
estructuras, aunque con ciertas reglas de apego a tipos. En el ejemplo anterior se utiliza
también un operador de asignación sobrecargado, ya que la instrucción y no una asignación
escalar definida, fue la que activó una operación de copia de estructuras.

2.10.4.1 OPERADORES COMO LLAMADAS A FUNCION.

Hay dos formas en las que se pueden implantar operadores para objetos de clase: como
funciones miembro y como amigos. Un operador unario aplicado a un objeto es equivalen

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 53


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

te a una llamada a una función. Dados un objeto W y un operador unario @ , la expresión


@W es equivalente a las llamadas a funciones:

W.operator@() // uso de un operador con función miembro.


operator@(W) // uso de un operador con función friend.

Un operador binario aplicado a los objetos es equivalente también a una llamada a función.

Dados los objetos X y Y, y un operador @, la expresión X @ Y es equivalente a las


llamadas a funciónes:

X.opertor@(Y) // uso de un operador con función miembro.


Operator@(X, Y) // uso de un operador con función friend.

El código anterior demuestra que los operadores pueden invocar dos funciones diferentes;
una función que es miembro y otra que es amigo.

2.10.4.2 OPERADORES SOBRECARGADOS COMO FUNCIONES MIEMBRO.

Las funciones que implantan operadores son un tanto inusuales. Para comenzar, sus
nombres deben comenzar con la cadena operator, seguida de los caracteres que representan
el operador que se implanta. Por ejemplo la función miembro para implantar el operador de
adición tendría que llamarse operator+ . La segunda restricción se aplica al número de
argumentos que pueden tomar estas funciones. Las funciones miembro que implantan
operadores unarios no deben tomar argumentos, en tanto que las que implantan operadores
binarios pueden tomar solo un argumento.

El siguiente código muestra operadores sobrecargados implantados como funciones


miembro.

class Counter
{
public:
int value;
Counter(int i)
{
value = i;
}
Counter operator!(); // operador unario.
Counter operator+(Counter & c); // operador binario.
};

Counter Counter::operator!()
{
return Counter( ! value );
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 54


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Counter Counter::operator+( Counter & c)


{
return Counter( value + c.value);
}

void main()
{
Counter c1(3), c2(5); // se crean 2 objetos tipo counter.
c1 = ! c1; // se aplica el operador unario
c1 = c1 + c2; // se aplica el operador binario
}

El uso de los operadores en la función main() es completamente intuitivo, y no requiere que


el usuario conozca los detalles de la implantación de clases para averiguar cual será el
recultado de las operaciones.

La restricción en el número de argumentos (solamente uno), limita las posibilidades; pero


esto lo podemos resolver sobrecargando el mismo operador tantas veces como sea
necesario, vea un ejemplo de como se sobrecarga el operador de adición tres veces.

class M
{
public:
int value;
M(int i) { value = i; }
M operator+(M& m);
M operator+(int i);
M operator+(double d);
};

M M::operator+(M& m)
{
return M(value + m.value);
}

M M::operator+(int i)
{
return M(value + i);
}

M M::operator+(double d)
{
returnM(value + d);
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 55


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void main()
{
M m1(3), m2(10); // se crean dos objetos de clase M.
m1 = m1 + m2; // uso M::operator+(M&)
m1 = m2 + 200; // uso M::operator+(int)
m1 = m2 + 3.14159; // uso M::operator+(double)
}

2.10.4.3 OPERADORES SOBRECARGADOS COMO FUNCIONES FRIEND.

En el siguiente ejemplo el operador + se declara como función friend y el operador = como


función miembro de la clase X, ya que el operador = solo puede sobrecargarse como
función miembro, lo que implica que el operador = global no puede ser sobrecargado. Los
diseñadores del lenguaje decidieron que permitir que las funciones friend cambiaran el
significado del operador de asignación causaría mas problemas de los que resolvería.

class X
{
friend X operator+(X&, X&);
public:
int value;
X(int i) { value = i; }
X& operator = (X&);
};

X& X::operator = (X& b)


{
value = b.value;
return *this;
}

X operator+(X& a, X& b)
{
return X(a.value + b.value);
}

void main()
{
X g(2), h(5), i(3);
G = h +h +i;
}

En general, los operadores friend sobrecargados se comportan de manera muy similar a las
funciones miembro.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 56


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.11 POLIMORFISMO

El origen del término polimorfismo es simple: proviene de las palabras griegas poly
(muchos) y morphos (forma) multiforme. El polimorfismo describe la capacidad del código
C++ de comportarse de diferentes maneras dependiendo de situaciones que se presenten al
momento de la ejecución.

El concepto de polimorfismo es crucial para la programación orientada a objetos. En su


concepción relativa a C++, el término polimorfismo se utiliza para describir el proceso
mediante el cual se puede acceder a diferentes implementaciones de una función utilizando
el mismo nombre. Por esta razón el polimorfismo se define a veces mediante la frase “una
interface métodos múltiples”. Esto significa que en general se puede acceder a toda una
clase de operaciones de la misma manera, aunque las acciones concretas que estén
asociadas a cada una de las operaciones pueda ser diferente.

En C++, el polimorfismo se admite tanto en el momento de la ejecución como en el


momento de la compilación. La sobrecarga de operadores y de funciones es un ejemplo de
polimorfismo en el momento de la compilación. Sin embargo, aunque la sobrecarga de
operadores y de funciones son muy potentes, no pueden llevar a cabo todas las tareas que
requiere un verdadero lenguaje orientado a objetos. Por tanto, C++ permite también el
polimorfismo en el momento de la ejecución mediante el uso de clases derivadas y de
funciones virtuales.

2.11.1 FUNCIONES VIRTUALES.

El polimorfismo en el momento de la ejecución se consigue mediante el uso de tipos


derivados y funciones virtuales. En pocas palabras, una función virtual es una función que
se declara como virtual en una clase base y que se define en una o más clases derivadas.

Lo que hace especiales a las funciones virtual es que cuando se accede a una de ellas
utilizando un puntero de clase base señala a un objeto de clase derivada, C++ determina
qué función debe llamar en el momento de la ejecución, basándose en el tipo del objeto al
cual apunta. Por tanto, si apunta a diferentes objetos, se ejecutan versiones diferentes de la
función virtual.

Como ejemplo examine el siguiente código:

#include<iostream.h>
class Base
{
public:
virtual void quien() { cout << “Base \n”; }
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 57


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class primera_deriv : public Base


{
public:
void quien() { cout << “ Primera derivación \n”; }
};

class seguna_deriv : public Base


{
public:
void quien() { cout << “ Segunda derivación \n”; }
};

main(void)
{
Base obj_base;
Base *p;
Primera_deriv obj_primera;
Segunda_deriv obj_segunda;
p = &obj_base;
p->quien();
p = &obj_primera;
p->quien();
p = &obj_segunda;
p->quien();
return 0;
}

El programa produce la siguiente salida.

Base
Primera derivación
Segunda derivación.

La clave de la utilización de funciones virtual para lograr el polimorfismo en el momento


de la ejecución es que se debe acceder a esas funciones mediante el uso de un puntero
declarado como puntero de la clase base.

Parte de la clave para aplicar con éxito el polimorfismo consiste en comprender que la base
y las clase derivadas forman una jerarquía, que va desde la mayor generalización a la menor.
Por tanto la clase base cuando se utiliza correctamente, proporciona todos los elementos
que puede utilizar directamente una clase derivada, mas aquellas funciones que la clase
derivada debe implementar por sí misma. Sin embargo dado que la forma de la interface
está determinada por la clase base todas las clases derivadas van a compartir esa interface .

El código siguiente utiliza la clase figura para derivar dos clase concretas llamadas cuadro y
triángulo.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 58


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include<iostream.h>
class Figura
{
protected:
double x, y:
public:
void pon_dim(double I, double j) { x = I; y = j; }
virtual void mostrar_area() { cout << “función no implementada \n”;}
};

class triángulo : public Figura


{
public:
void mostrar_area()
{
cout<<”Triangulo de altura “ << x <<” y base ” << y << ”
y área ” x * y * 0.5;
}
};

class cuadrado : public Figura


{
public:
void mostrar_area()
{
cout << “Cuadrado de lado ” << x <<” por ” << y <<
“área = ” << x * y <<”\n”;
}
};

main (void )
{
Figura *p;
triangulo trian;
cuadrado cuad;
p = &trian;
p->pon_dim(10.0, 5.0);
p->mostrar_area();
p = &cuad;
p->pon_dim(10.0, 5.0);
p->mostrar_area();
return 0;
}

Como se puede ver al examinar este programa, la interface de cuadrado y de triángulo es la


misma, aunque cada uno de ellos proporcione sus propios métodos para calcular el área de
cada uno de sus objetos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 59


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

2.12 EJEMPLOS DE PROGRAMACION ORIENTADA A OBJETOS

a) Este pequeño programa trata de calcular el área y la longitud de una circunferencia. Es


sencillo y usa clases e instancias.

#include<iostream>

using namespace std;

const double pi=3.141516;

class calcular
{
double radio,area,longitud;

public:
void iniciar(void);
void entradaDatos(void);
void salidaDatos(void);
} calcular1;

int main(void);
{
calcular calcular2;
calcular1.iniciar();
calcular2.iniciar();

calcular1.entradaDatos();
calcular2.entradaDatos();

calcular1.salidaDatos();
calcular2.salidaDatos();
return 0;
}

void calcular::iniciar(void)
{
cout <<"PROGRAMA QUE CALCULA EL AREA Y LONGITUD DE UNA
CIRCUNFERENCIA"<<"\n\n";
}

void calcular::entradaDatos(void)
{
cout<<"INTRODUZCA EL RADIO DE LA CIRCUNFERENCIA"<<"\n";
cin>>radio;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 60


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

area=pi*radio*radio;
longitud=2*pi*radio;
}

void calcular::salidaDatos(void)
{
cout<<"AREA =\t\t" <<area <<"\n";
cout<<"LONGITUD =\t\t" <<area <<"\n\n";
}

b) El siguiente ejemplo implementa un Programa Orientado a Objetos donde el Esquema


de la clase se dispone en un archivo ‘ .h’, las interfaces en un segundo archivo ‘.cpp’ y la
creación de objetos en un archivo ‘.cpp’.

//implementacion del esquema de la clase


// se graba con una extension .h
//#include <stdlib.h>
class ejemplo
{
private:
int a,b,c;
public:
ejemplo(int,int);//funcion constructora
void leer(void);
void imprimir();
//las funciones set permiten asignar valores a datos privados
void seta(int);
void setb(int);
void setc(int);
//las funciones get permiten recuperar valores de datos privados
int geta();
int getb();
int getc();
int mcd();
int producto(int,int);
};

//archivo que implementa las funciones de la clase ejemplo


// se graba con el nombre ejemplo.cpp

#include <iostream.h>
#include <d:/lab1sis2210/ejemplo.h>
ejemplo::ejemplo(int d1,int d2)
{
a=d1;
b=d2;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 61


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void ejemplo::leer()
{
cout<<"\n valor para la variable a:";
cin>>a;
cout<<"\n valor para la variable b:";
cin>>b;
}
void ejemplo::imprimir()
{
cout<<"\n valor para la variable a="<<a;
cout<<"\n valor para la variable b="<<b;
};

void ejemplo::seta(int d)
{
a=d;
}

void ejemplo::setb(int d)
{
b=d;
}

void ejemplo::setc(int d)
{
c=d;
}

int ejemplo::geta()
{
return a;
}

int ejemplo::getb()
{
return b;
}

int ejemplo::getc()
{
return c;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 62


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int ejemplo::mcd()
{
int n,m;
n=a;m=b;
while (n>0)
if (n>=m)
n=n-m;
else
m=m-n;
return m;
}
int ejemplo::producto(int x,int y)
{
int prod=0,cont=0;
while (cont<y)
{
prod=prod+x;
cont++;
};
return prod;
}

//implementa objetos a partir de la clase ejemplo


#include <iostream.h>
#include <conio.h>
#include <d:/lab1sis2210/ejemplo.cpp>
main()
{
ejemplo e(18,24); //se invoca a la funcion constructora
e.imprimir(); //invoca a la funcion imprimir del objeto e
getch();
cout<<"\n el maximo comun divisor es: "<<e.mcd();
cout<<"\n valor para la variable c:";
int dat;
cin>>dat;
e.setc(dat);
cout<<"\n valor de la variable c:"<<e.getc();
cout<<"\n el producto es:"<<e.producto(e.geta(),e.getc());

return 0;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 63


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

c) El ejemplo siguiente implementa una jerarquía de clase e ilustra la herencia y el


polimorfismo.

//implementacion de una jerarqui de clases


//se graba con el nombre 'herencia.h'
#include <stdlib.h>
class persona
{
private:
int ci;
char nombre[30];
int edad;
public:
virtual void leer();
virtual void impre();
};

class estudiante:public persona


{
private:
char carrera[15];
public:
virtual void leer();
virtual void impre();
};
class docente:public persona
{
private:
float salario;
public:
virtual void leer();
virtual void impre();
};

//implementa las interfaces de la jerarquia de clases.


// se graba con el nombre 'herencia.cpp'

#include <d:/lab2sis2210/herencia.h>
#include <iostream.h>
void persona::leer()
{
cout<<"\n introducir C.I.:";
cin>>ci;
cout<<"\n introducir Nombre:";
cin>>nombre;
cout<<"\n introducir Edad:";
cin>>edad;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 64


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

}
void persona::impre()
{
cout<<"\n C.I.:"<<ci;
cout<<"\n Nombre:"<<nombre;
cout<<"\n Edad:"<<edad;
}
void estudiante::leer()
{
persona::leer();
cout<<"\n Introducir carrera:";
cin>>carrera;
};
void estudiante::impre()
{
persona::impre();
cout<<"\n Carrera:"<<carrera;
}
void docente::leer()
{
persona::leer();
cout<<"\n Introducir Salario:";
cin>>salario;
};
void docente::impre()
{
persona::impre();
cout<<"\n Salario:"<<salario;
}

//implementa objetos a partir de las clases definidas en 'herencia.h' y 'herencia.cpp'

#include <d:/lab2sis2210/herencia.cpp>
#include <iostream.h>
#include <conio.h>
void main()
{
persona p;
//cout<<"\n tamaño de un entero :"<<sizeof(int);
/*p.leer();
p.impre();
estudiante e;
e.leer();
e.impre();

docente d;
d.leer();

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 65


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

d.impre();*/
persona *a[5];
int i,tipo,n;
cout<<"\n cantidad de personas:";
cin>>n;
for (i=0;i<n;i++)
{
cout<<"\n tipo : ESTUDIANTE = 0 , DOCENTE = 1 ?:";
cin>>tipo;
if (tipo==0)
a[i]=new estudiante;
else
a[i]=new docente;
a[i]->leer();
};
cout<<"\n contenido del vector:";
for (i=0;i<n;i++)
a[i]->impre();
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 66


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 3

INTRODUCCION A LAS ESTRUCTURAS DE DATOS


ESTATICAS
La implementación de una aplicación computacional requiere la especificación de un
conjunto de variables u objetos que sustentan la información a procesar, el programa
contiene elementos abstractos, que durante la ejecución del mismo, almacenaran los valores
con los cuales se desarrollan los diferentes cálculos para la obtención de los resultados
deseados. La forma que el analista configura los elementos abstractos para el
almacenamiento de datos se denomina Estructura de datos del Programa y se los puede
definir de la siguiente manera:

 Una estructura de Datos es toda forma particular de organizar la información en la


memoria con fines de procesamiento.
 Una Estructura de datos es el modelo lógico de la representación física de los datos
en la memoria.
 Una estructura de Datos es la forma de establecer y configurar el conjunto de
variables que se constituyen en el sustento de los datos en la memoria durante la
ejecución de la aplicación.

3.1. CLASIFICACIÓN DE LOS TIPOS DE DATOS SEGÚN SU ESTRUCTURA

La s Estructura de datos se pueden clasificar en dos tipos genéricos:

 Simples: Los tipos simples son cuando cada dato representa un único elemento

Estándar: Están definidos por defecto por el lenguaje


entero, real, carácter, booleano

No estándar: Tipos simples definidos por el usuario


enumeración, subrango

 Estructurados: son cuándo un dato es una estructura que se construyen a partir de


otros complementos.

Estáticos: Ocupan un tamaño de memoria fijo, que se tiene que definir antes de
declararlo.
arrays, cadena, registros, ficheros, conjuntos

Dinámicos: La estructura no ocupa un tamaño fijo de memoria, sino que ocupa la


memoria que ocupa en cada momento. Se van a manejar a través del tipo de dato
puntero.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 67


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Puntero: Es una variable cuyo contenido es una dirección de memoria y esa


dirección de memoria corresponde a la dirección de memoria de otra variable, que
es la variable apuntada.

punteros, listas enlazadas, árboles, grafos

En el presente capítulo se hace énfasis en la estructura de datos más importante y


fundamental en el procesamiento de la información, los arreglos.

3.2. ARREGLOS.

Un arreglo se define como un conjunto finito, ordenado y homogéneo de celdas de


memoria referenciadas por un nombre único, nombre del arreglo, y que pueden almacenar
datos del mismo tipo.

Es finito porque tiene un número determinado de elementos. Es Homogéneo porque todos


los elementos almacenados van a ser del mismo tipo. Es Ordenado porque se puede acceder
a cada elemento del array de manera independiente, porque va a haber una forma de
referenciar a cada elemento (celda). Para referenciar cada elemento de un array se emplea
índices (valor que directa o indirectamente referencia la posición del array).

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 68


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

3.2.1. ARREGLOS UNIDIMENSIONALES. VECTORES.

Un arreglo (array) unimensional, conocido también como Vector, se caracteriza porque


requiere un solo índice o subíndice parea referencias a un elemento o una celda del
conjunto total disponible.

Para referenciar un elemento de un array se emplea el nombre del array y entre corchetes [ ]
el índice que determina la posición de ese elemento en el array.

Nombre_array[numero_celda]

El rango o longitud de un vector o array lineal es la diferencia entre el índice de valor


máximo y el índice de valor mínimo de ese array + 1. Normalmente los índices comienzan
a enumerarse, es decir, el valor mínimo del índice es 0 ó 1, dependiendo del lenguaje (en
Pascal con 1 y en C con 0). Sin embargo nadie impide que comiencen en cualquier otro
valor.

Los arrays se almacenan siempre en posiciones consecutivas de memoria y se puede


acceder a cada elemento del array de manera independiente a través de los índices. Un
índice no tiene por qué ser un valor constante, sino que puede ser también una variable o
una expresión que al ser evaluada devuelva ese índice.

DECLARACIÓN DE UN ARRAY UNIDIMENSIONAL: VECTOR:

La declaración es muy similar a la declaración de cualquier tipo de dato simple, debiendo


adicionar la especificación de la cantidad de celdas que conformaran el vector con un
número entero positivo entre corchetes.

Tipo_dato nombre_arreglo[tamaño]

Ejemplo:

int a[100];

‘a’ es un arreglo unidimensional con 100 celdas disponibles, numeradas desde la 0


hasta la 99 y que puede almacenar datos enteros únicamente.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 69


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

float b[30];

‘b’ es un arreglo unidimensional con 30 celdas disponibles, numeradas desde la 0


hasta la 29 y que puede almacenar datos reales únicamente.

char nom[45];

‘nom’ es un arreglo unidimensional con 45 celdas disponibles, numeradas desde la 0


hasta la 44 y que puede almacenar datos tipo carácter únicamente.

ALMACENAMIENTO DE DATOS EN UN VECTOR.

El almacenamiento de datos en un vector es el proceso mediante el cual se depositan los


valores, es decir datos, en las diferentes celas del arreglo, esta operación se puede realizar
de 3 formas:

a) Por inicialización en la declaración del arreglos.

Esta forma de almacenamiento es muy frecuente cuando se dese que los datos
almacenados en el vector siempre sean los mismos al empezar la ejecución de la
aplicación.

Los datos se almacenan antes de la ejecución del programa, es decir, en proceso de


compilación.

Ejemplo:

int a[10]={4,8,3,9};

Los cuatro valores inicializan las primeras cuatro celdas del vector. Las
celdas restantes del vector que no son inicializadas toman el valor 0 por
defecto:

b) por una función de asignación.

Esta forma de almacenamiento de datos se emplea cuando:


o La aplicación se está ejecutando.
o Los datos a almacenar se generan internamente por medio de una función
específica, la más usual la función ‘random’, datos aleatorios.
o Cada vez que se ejecuta la aplicación, los datos que se almacena en el vector
pueden ser o no los mismos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 70


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Ejemplo:

for (i=0;i<10;i++)
a[i]= random(20);

En las 10 celdas del vector ‘a’, desde la 0 hasta la 9, se almacenan valores


aleatorios generados por medio de la función ‘random’.

c) Por una función de entrada de datos.

Los datos que almacenan en el vector, se introducen por el usuario desde el teclado durante
la ejecución del programa.

Se emplea dominantemente cuando se desea almacenar un conjunto reducido de datos y de


acuerdo a la necesidad del usuario para la ejecución del programa.

Ejemplo:

for (i=0;i<10;i++)
cin>>a[i];

En las 10 celdas del vector ‘a’, desde la 0 hasta la 9, se almacenan valores


introducidos desde el teclado por medio de la función ‘cin’.

Una vez que los datos están almacenados en el vector, estos se encuentran disponibles para
el procesamiento durante toda la ejecución del programa.

MANEJO DE VECTORES DESDE UNA APLIACION OO.

El procesamiento de datos almacenados en un vector desde una aplicación orientada a


Objetos supone que de manera previa se realizan las siguientes actividades:

 Especificación del diagrama de la clase


 Implementación de la clase.
 Implementación de las funciones de la clase
 Desarrollo de una aplicación que utiliza objetos del tipo vector.

Estos pasos genéricos contendrán características específicas de acuerdo al problema que se


desea resolver, por ejemplo una ilustración en el procesamiento de vectores podría ser la
siguiente:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 71


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

a) Diagrama de la clase ‘Tvector’

Dónde:
a[], es el nombre del vector que contiene la clase.
n, es la cantidad de celdas que almacenaran datos.
leer(), es la función que almacena datos en las ‘n’ primeras celdas
del vector.
imprimir(), es la función que muestra el contenido de las n primeras
celdas del vector.
buscar(), es la función que verifica si un vlor ‘clave’ esta o no en el
vector.

Nota: Si los datos a y n de la clase Tvector son Privados, entonces es


necesario incorporar las funciones ‘set’ y ‘get’ para el acceso a los mismos
desde otras clases.

b) Implementación del esquema de la clase.

La implementación del esquema de la clase se desarrolla en un archivo ‘.h’, para el


ejemplo que se plantea se tiene el siguiente código que se graba en un archivo
‘vector.h’

class Tvector
{
//private:
public:
int a[50];
int n;
public:
Tvector(int);
void setn(int);
int getn();
int geta(int);
void seta(int,int);
void leer();
void imprimir();

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 72


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int buscar(int);
//otras funciones de la clase vector
void qsort(int[],int,int);

};

c) Implementación de las funciones de la Clase.

Las funciones de una clase se implementan en un archivo ‘.cpp’ independiente, con


el fin de incorporar las características de la POO. Para el ejemplo que se desarrolla
en este capítulo, esta implementación considera las funciones ‘set’ y get’, debido a
que los datos a y n son privados y serán guardados en un archivo ‘vector.cpp’.

#include <d:/lab3sis2210/vector.h>
#include <iostream.h>
#include <stdlib.h>
Tvector::Tvector(int t)
{
n=t;
}
void Tvector::setn(int t)
{
n=t;
}
int Tvector::getn()
{
return n;
}
void Tvector::seta(int dat,int cel)
{
a[cel]=dat;
}
int Tvector::geta(int cel)
{
return a[cel];
}
void Tvector::leer()
{
int i;
randomize();
for (i=0;i<n;i++)
a[i]=random(20)+1;
}
void Tvector::imprimir()
{
int i;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 73


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

for (i=0;i<n;i++)
cout<<a[i]<<" , ";
cout<<"\n";
}
int Tvector::buscar(int dat)
{
//BUSQUEDA SECUENCIAL O LINEAL
int i=0;
while (i<n && dat!=a[i])
i++;
if (i==n)
return (-1);
else
return i;
}
Void Tvector::qsort(int x[],int p,int q)
{
if(p<q)
{
int piv=x[p];
int i=p,j=q+1;
while (i<j)
{
do {i++;} while (x[i]<=piv && i<=q);
do {j--;} while (x[j]>piv && j>=p);
if (i<j)
{
int aux=x[i];
x[i]=x[j];
x[j]=aux;
};
};
x[p]=x[j];
x[j]=piv;
qsort(x,p,j-1);
qsort(x,j+1,q);
};
}

d) Generación y uso de objetos a partir de la clase Tvector.

Se debe desarrollar otro programa ‘.cpp’ donde se crea objetos a partir de la clase
Tvector y se emplea las funciones del objeto creado para resolver un problema
determinado. En el ejemplo que se desarrolla el programa puede ser ‘vecprub.cpp’.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 74


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

#include <d:/lab3sis2210/vector.cpp>
#include <stdlib.h>
#include <iostream.h>
int cant, resp;
main()
{

cout<<"\n tamaño del primer vector:";


cin>>cant;

Tvector v(cant);
v.leer();
v.imprimir();
cout<<"\n tamaño del segundo vector:";
cin>>cant;
Tvector k(cant);
k.leer();
k.imprimir();
// mostrar los elemento del vecto v que se encuentran en el vector k
Tvector r(20);
int i,j=0;
for (i=0;i<v.getn();i++)
if (k.verificar(v.geta(i))>=0)
{
r.seta(v.geta(i),j);
j++;
};
r.setn(j);
cout<<"\n resultado de los elementos comunes\n";
r.imprimir();
v.qsort(v.a,0,v.getn()-1);
v.imprimir();
return 0;
}

El programa anterior, crea dos objetos ‘v’ y ‘k’ partir de la clase Tvector,
almacena cantidades de datos en cada vector de los objetos en forma
aleatoria, por medio de la función ‘random’ y crea un tercer objerto ‘r’ en
cuyo vector se tiene los valores comunes de los vectores de los objetos ‘v’ y
‘k’.

También es recomendable desarrollar otras clases que incorporen operaciones con el


manejo de vectores.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 75


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

3.2.2. ARREGLOS BIDIMENSIONALES. MATRICES.

En un arreglo Bidimensional, el conjunto de celdas se organizan como una tabla, es decir,


se tiene filas y columnas.

En un arreglo unidimensional o vector cada elemento se referencia por un índice, en un


arreglo bidimensional cada elemento se va a referenciar por 2 índices, y ahora la
representación lógica ya no va a ser un vector, sino una matriz.

Un array bidimensional de M filas y N columnas es un conjunto de M*N elementos, todos


del mismo tipo, cada uno de los cuales se referencia a través de 2 subíndices. El primer
subíndice podrá variar entre 0 y M-1, y el segundo índice variará entre 0 y N-1.

DECLARACIÓN DE UN ARRAY BIDIMENSIONAL: MATRIZ:

La declaración es muy similar a la declaración de cualquier tipo de dato simple o de un


arreglo unidimensional, debiendo adicionar la especificación de la cantidad de filas y
columnas que contendrá la matriz.

Tipo_dato nombre_arreglo[tamaño_filas][tamaño_columnas];

Ejemplo:

int a[10][10];

‘a’ es un arreglo bidimensional con 100 celdas disponibles, organizadas en 10 filas


y 10 columnas, las filas se numeran desde la 0 hasta la 9, las columnas se numeran
desde la 0 hasta la 9 y se puede almacenar datos enteros únicamente.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 76


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

float b[30][5];

‘b’ es un arreglo bidimensional con 150 celdas disponibles, organizadas en 30 filas


y 50 columnas, las filas se numeran desde la 0 hasta la 29, las columnas se numeran
desde la 0 hasta la 4 y se puede almacenar datos reales únicamente.

char lista[10][45];

‘lista’ es un arreglo bidimensional con 10 filas, numeradas desde la 0 hasta la 9 y


cada fila tiene 45 columnas numeradas desde 0 0 hasta la 44 y se puede almacenar
datos tipo carácter únicamente. Esta declaración permite almacenar 10 cadenas de
caracteres de un máximo de 45 letras cada una.

ALMACENAMIENTO DE DATOS EN UN VECTOR.

Idéntico a lo establecido con los vectores.

El almacenamiento de datos en una matriz es el proceso mediante el cual se depositan los


valores, es decir datos, en las diferentes celas del arreglo, esta operación se puede realizar
de 3 formas:

a) Por inicialización en la declaración del arreglos.

Esta forma de almacenamiento es muy frecuente cuando se dese que los datos
almacenados en el vector siempre sean los mismos al empezar la ejecución de la
aplicación.

Los datos se almacenan antes de la ejecución del programa, es decir, en proceso de


compilación.

Ejemplo:

int b[10][10]={{4,8,3,9},{4,2,8,5},{9,4,2,7}};

Los tres grupos de valores inicializan las primeras tres filas de la matriz. Las
celdas restantes de la matriz que no son inicializadas toman el valor 0 por
defecto:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 77


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

b) por una función de asignación.

Esta forma de almacenamiento de datos se emplea cuando:


o La aplicación se está ejecutando.
o Los datos a almacenar se generan internamente por medio de una función
específica, la más usual la función ‘random’, datos aleatorios.
o Cada vez que se ejecuta la aplicación, los datos que se almacena en el vector
pueden ser o no los mismos.

Ejemplo:

for (i=0;i<10;i++) // filas


for (j=0;j<10;j++) // columnas
b[i][j]= random(20);

En las 100 celdas del vector ‘b, se almacenan valores aleatorios generados
por medio de la función ‘random’.

c) Por una función de entrada de datos.

Los datos que almacenan en el vector, se introducen por el usuario desde el teclado durante
la ejecución del programa.

Se emplea dominantemente cuando se desea almacenar un conjunto reducido de datos y de


acuerdo a la necesidad del usuario para la ejecución del programa.

Ejemplo:

for (i=0;i<4;i++) //filas


for (j=0;j<3;j++) //columnas
cin>>b[i][j];

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 78


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

En las 4 primeras filas y en las 3 primeras columnas de la matriz b’, se


almacenan valores introducidos desde el teclado por medio de la función
‘cin’.

Una vez que los datos están almacenados en el vector, estos se encuentran disponibles para
el procesamiento durante toda la ejecución del programa.

MANEJO DE UNA MATRIZ DESDE UNA APLIACION OO.

El procesamiento de datos almacenados en una Matriz desde una aplicación orientada a


Objetos es idéntico al proceso establecido con un vector, se desarrolla las siguientes
actividades:

 Especificación del diagrama de la clase


 Implementación de la clase.
 Implementación de las funciones de la clase
 Desarrollo de una aplicación que utiliza objetos del tipo vector.

Estos pasos genéricos contendrán características específicas de acuerdo al problema que se


desea resolver, por ejemplo una ilustración en el procesamiento de vectores podría ser la
siguiente:

a) Diagrama de la clase ‘matriz’

Donde:
a[][], es el nombre del vector que contiene la clase.
n y m, es la cantidad de filas y columnas de la matriz.
leer(), es la función que almacena datos en la matriz.
imprimir(), es la función que muestra el contenido de la matriz.
verificar(), es la función que verifica si un valor ‘clave’ está o no en
la matriz.

Nota: Si los datos a, n y m de la clase ‘matriz’ son Privados, entonces es


necesario incorporar las funciones ‘set’ y ‘get’ para el acceso a los mismos
desde otras clases.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 79


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

b) Implementación del esquema de la clase.

La implementación del esquema de la clase se desarrolla en un archivo ‘.h’, para el


ejemplo que se plantea se tiene el siguiente código que se graba en un archivo
‘matriz.h’

class matriz
{
public:
int a[10][10];
int n,m;
public:
matriz(int,int);
void seta(int,int,int);
void setn(int);
int geta(int,int);
int getn();
void setm(int);
int getm();
void leer();
void imprimir();
int verificar(int);
};

c) Implementación de las funciones de la Clase.

Las funciones de una clase se implementan en un archivo ‘.cpp’ independiente, con


el fin de incorporar las características de la POO. Para el ejemplo que se desarrolla
en este capítulo, esta implementación considera las funciones ‘set’ y get’, debido a
que los datos a y n son privados y serán guardados en un archivo ‘matriz.cpp’.

#include <iostream.h>
#include <stdlib.h>
#include <d:\sis2210a\matrizoo\matriz.h>
matriz::matriz(int f,int c) //function constructora
{
n=f;
m=c;

}
void matriz::seta(int valor,int f,int c)
{
a[f][c]=valor;
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 80


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

void matriz::setn(int f)
{
n=f;
}
int matriz::geta(int f,int c)
{
return a[f][c];
}
int matriz::getn()
{
return n;
};
void matriz::setm(int c)
{
m=c;
}
int matriz::getm()
{
return m;
}
void matriz::leer()
{
int i,j;
cout<<"\n almacenamiento de datos en la matriz";
//randomize();
for (i=0;i<n;i++)
for (j=0;j<m;j++)
{
// cout<<"\nvalor para la celda a["<<i<<"]["<<j<<"]=";
// cin>>a[i][j];
a[i][j]=random(30)+5;
};
}
void matriz::imprimir()
{
int i,j;
cout<<"\n contenido de datos en la matriz\n\n";
for (i=0;i<n;i++)
{
for (j=0;j<m;j++)
cout<<a[i][j]<<"\t";
cout<<"\n";
};
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 81


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

int matriz::verificar(int clave)


{
int i,j,sw=0;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
if (clave==a[i][j])
sw=1;
return sw;
}

d) Generación y uso de objetos a partir de la clase Tvector.

Se debe desarrollar otro programa ‘.cpp’ donde se crea objetos a partir de la clase
‘matriz’ y se emplea las funciones del objeto creado para resolver un problema
determinado. En el ejemplo que se desarrolla el programa puede ser ‘ejemmat.cpp’.

#include <iostream.h>
#include <d:\sis2210a\matrizoo\matriz.cpp>
int main()
{
//int p,q,r,s;
matriz m1(3,3);
m1.leer();
m1.imprimir();
return 0;
}

El programa anterior es simple y trata de ilustrar la creación de un objeto


‘m1’ a partir de la clase ‘matriz’ inicializando a las variables ‘m’ y ‘n’ con el
valor 3 es decir, si bien el tamaño de la matriz ‘a’ es de 10 filas y 10
columnas, se establece para el almacenamiento de datos únicamente las 3
primeras filas y las 3 primeras columnas, luego se genera datos en las 3
primeras filas y columnas y finalmente muestra el contenido de la matriz..

Es importante remarcar que la definición de clases que incorporan el manejo de


matrices deben estar en función a los requerimientos particulares de los problemas
que se desean resolver, de esta manera se puede lograr una configuración de clases
de tal forma que satisfagan una gran cantidad de requerimientos e con la empleo de
matrices u otras estructuras de datos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 82


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

CAPITULO 4

ESTRUCTURAS Y UNIONES

4.1. ESTRUCTURAS.

Todas las variables que se ha utilizado en los temas anteriores han sido de un único tipo,
incluso los arrays son variables con todos los elementos del mismo tipo. La finalidad de
una estructura es agrupar una o más variables, generalmente de diferentes tipos, bajo un
mismo nombre para hacer más fácil su manejo.

Dependiendo del tipo de información a procesar, es necesario agrupar un conjunto de


atributo (variables) respecto a un objeto de interés bajo un mismo denominativo. Por
ejemplo:

 Si se requiere procesar la información de una persona, entonces los atributos a


considerar pueden ser:
o Ci
o Nombre
o Dirección
o Teléfono
o Etc
Todos estos atributos relativos al objeto de interés (entidad) que pueden ser de
diferente tipo, se los debe agrupar en una sola variable u objeto.

 En algunos casos es necesario descomponer cierta información en elelemntos masd


basicos con fines de procesamiento, lo que supone la especificación de atributos de
una entidad, por ejemplo: Nombre_persona se puede descomponer en:
apellido_paterno, apellido_materno y nombre.

DEFINICION:
Una estructura es un conjunto finito de variables de diferente tipo o no
referenciadas por un nombre único y que permiten almacenar el valor en
cada variable simultáneamente.

Para el Procesamiento de una estructura es necesario de manera inicial definir el esquema


de la estructura.

4.1.1. ESQUEMA DE LA ESTRUCTURA.

El esquema de la estructura es la presentación gráfica del conjunto de variables, llamados


también campos o miembros de la estructura, relativos a un objeto de interés, permite
establecer de manera clara y simple la configuración y orden del conjunto de campos.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 83


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El diseño del esquema de la estructura es una tarea no obligatoria pero resulta importante
en función al grado de complejidad en el proceso de descomposición en atributos del objeto
de interés.

Ejemplo:

4.1.2. DECLRACION DE UN TIPO DE DATO ESTRUCTURA

Para crear una estructura hay que definir un nuevo tipo de datos y declarar una variable de
este tipo. La declaración de un tipo estructura, incluye tanto los elementos que la componen
como sus tipos. Cada elemento de una estructura recibe el nombre de miembro (campo del
registro). La sintaxis es la siguiente:

struct tipo _estructura


{
// Declaración de los miembros de la estructura;
};

Donde tipo_estructura es un identificador que nombra el nuevo tipo definido. La


declaración de un miembro de una estructura no puede contener calificadores de clase de
almacenamiento como extern, static, auto o register y no puede ser inicializado. Su tipo
puede ser: fundamental, array, puntero, unión, estructura o función.

Ejemplo:

struct persona
{
int ci;
char nombre[30];
char direc[20];
float est;
char sexo;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 84


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

En el ejemplo anterior se ha creado un nuevo tipo de dato llamado ‘persona’, este


nuevo tipo de dato es una estrucvtura que tiene 5 campos o miembros.

Las reglas para utilizar el nuevo tipo son las mismas que las seguidas para los tipos
predefinidos como float, int y char, entre otros. Esto es, después de definir un tipo
estructura, podemos declarar una variable de ese tipo.

4.1.3. DECLARACION DE UNA VARIABLE ESTRUCTURA.

Es importante tomar en cuenta que en un programa computacional únicamente las variable


u objetos son los elementos que pueden almacenar datos, por lo que es necesario la
declaración de las mismas.

La declaración de una variable estructura se puede realizar de dos maneras:

a) A PARTIR DE UN TIPO DE DATO.

Esta manera, la mas usual en la programación, requiere que de manera previa la declaración
de un tipo de dato struct y es similar a la declaración de variables a partir de los tipos
predefinidos, se emplea el siguiente formato:

struct tipo-estructura varible1, variable2,…..;

Ejemplo:

struct persona reg;

‘reg’ es una variable del tipo persona, es decir, contiene los mismos campos
especificados en el tipo de dato persona.

persona aux;

En C++, no es necesario especificar la palabra reservado ‘struct’ antes del


tipo de dato estructura, siendo totalmente valido.

b) Simultáneamente a la declaración del tipo de dato.

La definición de las variables estructuras se purede realizar también justamente a


continuación de la declaración del nuevo tipo.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 85


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

struct persona
{
int ci;
char nombre[30];
char direc[20];
float est;
char sexo;
} reg1, reg2;

En esta declaración se ha desarrollado la creación de un nuevo tipo de dato


‘persona’ y simultáneamente la definición de dos variables reg1 y reg2.

También es posible desarrollar la definición de variables de manera directa:

struct
{
int ci;
char nombre[30];
char direc[20];
float est;
char sexo;
} per1, per2;

En esta definición se tiene dos variables per1 y per2 y no se ha declarado


ningún tipo de dato nuevo.

4.1.4. ACCESO A LOS CAMPOS DE UNA VARIABLE ESTRUCTURA

Una variable estructura hace referencia grupal al conjunto de miembros o campos que lo
conforman, sin embargo en el procesamiento de la información es necesario tener la
posibilidad de procesar de manera individual cada valor almacenado en cada campo.

El Operador ‘.’ (punto) permite accederé a cada campo de manera individual, donde se
utiliza la siguiente notación:

Varible_estructura.miembro

Ejemplo:
Persona reg;


Gráficamente reg tiene la siguiente forma:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 86


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

Según corresponda se debe escribir:

reg.ci
reg.nombre
reg.direc
reg.est
reg.sexo

Para acceder a cada uno de los campos.

4.1.5. OPERACIONES CON ESTRUCTURAS.

En un programa se puede realizar operaciones con variables tipo estructura.

a) Asignación.

Dos variables estructura se pueden asignar únicamente si son estructuras del mismo tipo, es
decir, si son compatibles. La asignación supone una asignación equivalente a campo por
campo, el contenido de todos los campos de una variable son asighnadas a todos los
campos de otra variable.

Ejemplo:
persona reg, aux,

….
aux=reg;

La información contenida en los campos de aux son asignados o transferidos a todos


los campos de reg, es decir tanto aux como reg almacenan la misma información en
sus campos.

b) Inicializacion.

Una variable estructura puede ser inicializada con valores en los diferentes campos en el
momento de su definición, esto es similar a la inicialización de los tipos predefinidos.

Ejemplo:

persona reg={5555,”Juan Carlos”, “Arce 234”,1.75,’M’};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 87


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

se tiene:

c) Acceso a los miembros de la Estructura.

Como se ha indicado anteriormente el acceso a los miembros de la estructura se realiza por


medio del operador ‘.’.

Ejemplo:
float est=reg.est;

d) Obtener la Direccion de Memoria.

Esta es una operación muy importante cuando se debe procesar la información contenida en
una estructura por medio de Punteros.

Ejemplo:

Persona *pt=&reg;

Otras operaciones a realizar en el procesamiento de la información contenida en una


estructura se realizan campo por campo de manera individual.

4.1.6. ARREGLOS DE ESTRUCTURAS.

Una variable estructura almacena la información de un solo objeto de interés en un


momento dado, si se requiere procesar simultáneamente la información de varios objetos de
interés, entonces se puede definir varias variables tipo estructura, este camino no siempre es
el mejor, lo más recomendable es declara un arreglo de estructuras, esto significa que cada
celda del vector contiene una estructura de un tipo determinado.

Ejemplo: primero declaramos un tipo de datos estrutura.

typedef struct persona


{
int ci;
char nombre[30];
float est;
} tpersona;

La declaración de vector de estructuras se puede realizar de la siguiente forma:

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 88


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

struct persona lista[50];

‘lista’ es un vector de 50 celdas y cada celda contiene una estructura del tipo
persona.

También es posible realizar la siguiente declaración:

tpersona curso[50];

‘curso’ es un vector de 50 celdas y cada celda contiene una estructura del tipo
persona.

Gráficamente:

El siguiente programa ilustra el procesamiento de la información de un vector de


estructuras en una aplicación orientada a objetos.

Archivo personas.h

struct persona
{
int ci;
char nombre[30];
float est;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 89


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

class personavec
{
//private:
public:
// int a[50]={5,7,8};
persona lista[50];
int n;
public:
personavec(int);
void leer();
void imprimir();
int verificar(int);
//otras funciones de la clase vector
void ordenar(persona[],int);
float promest();
//otras funciones de la clase pesonavec
};

Archivo personas.cpp

#include <d:/lab4sis2210/persona.h>
#include <iostream.h>
#include <string.h>
personavec::personavec(int t)
{
n=t;
lista[0].ci=123;
strcpy(lista[0].nombre,"luisa");
lista[0].est=1.7;
lista[1].ci=789;
strcpy(lista[1].nombre,"pedro");
lista[1].est=1.63;
lista[2].ci=765;
strcpy(lista[2].nombre,"ana");
lista[2].est=1.75;
lista[3].ci=4653;
strcpy(lista[3].nombre,"mario");
lista[3].est=1.85;
}

void personavec::leer()
{
int i;
for (i=0;i<n;i++)
{
cout<<"\n ingresar C.I.:";
cin>>lista[i].ci;

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 90


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

cout<<"\n ingresar NOMBRE:";


cin>>lista[i].nombre;
cout<<"\n ingresar ESTATURA:";
cin>>lista[i].est;
};
}

void personavec::imprimir()
{
int i;
cout<<"\n reporte completo del vector de personas";
for (i=0;i<n;i++)
{
cout<<"\n C.I.:"<<lista[i].ci;
cout<<"\n NOMBRE:"<<lista[i].nombre;
cout<<"\n ESTATURA:"<<lista[i].est;
};
}

int personavec::verificar(int dato)


{
int i=0;
while (i<n && dato!=lista[i].ci)
i++;
if (i==n)
return -1;
else
return i;
}

void personavec::ordenar(persona x[],int y)


{
persona aux;
int i,j;
for (i=0;i<y-1;i++)
for (j=i+1;j<y;j++)
if (strcmp(x[i].nombre,x[j].nombre)<0)
{
aux=x[i];
x[i]=x[j];
x[j]=aux;
}
}

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 91


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

float personavec::promest()
{
int i,suma=0;
float prom;
for (i=0;i<n;i++)
suma+=lista[i].est;//suma=suma+lista[i].est;
prom=suma/n;
return prom;
}

Archivo que implementa objetos:

#include <d:/lab4sis2210/persona.cpp>
#include <iostream.h>

main()
{
personavec pv(4);
//pv.leer();
pv.imprimir();
int clave;
cout<<"\n\n C.I. de la persona a buscar en el vector:";
/*cin>>clave;
int resp=pv.verificar(clave);
if (resp!=-1)
cout<<"\n se encuentra en la celda :"<<resp;
else
cout<<"\n NO se encuentra en el vector.";*/
cout<<"\n\n ordenando el vector\n";
pv.ordenar(pv.lista,pv.n);
pv.imprimir();
return 0;
}

4.1.7. ESTRUCTURAS ANIDADAS

Una estructura anidada se presenta cuando uno o más miembros de la estructura


constituyen es si otra estructura, es decir, una estructura dentro de otra.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 92


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El procesamiento de las estructuras anidadas es similar al de una estructura simple.

Declaración:

a) en un solo bloque.

struct persona
{
int ci;
struct // estructura anidad
{
char nom[15];
char paterno[15];
char materno[15];
} nombre;
char direc[20];
float est;
char sexo;
};

b) Por declaraciones independientes.

//primero todas las estructuras internas.


Struct regnombre
{
char nom[15];
char paterno[15];
char materno[15];
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 93


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

// al final la estructura principal

struct persona
{
int ci;
struct regnombre nombre; // estructura anidada
char direc[20];
float est;
char sexo;
};

4.2 UNIONES.

Una Unión es un conjunto finito de variables de diferente tipo o no referenciadas por un


nombre único y que comparten el mismo espacio de almacenamiento.

A diferencia de las estructuras, el tamaño de una Union es equivalente al tamaño del campo
más grande, mientras que el tamaño de una estructura es equivalente a la suma del tamaño
de todos sus campos.

Una unión es una variable que puede contener, en distintos instantes de la ejecución del
programa, datos de diferentes tipos. Esto permite manipular diferentes tipos de datos
utilizando una misma zona de memoria, la reservada para la variable unión.

La declaración de una unión tiene la misma forma que la declaración de una estructura,
excepto que en lugar de la palabra reservada struct se pone la palabra reservada union. Por
lo tanto, todo lo expuesto para las estructuras es aplicable a las uniones, con la excepción de
que de los miembros especificados, en un instante sólo está uno presente. La sintaxis para
declarar una unión es:

a) Declaración de un tipo de dato ‘union’.

union tipo _union


{
// Declaración de los miembros de la union;
};

Ejemplo:

union bloque
{
int a;
float b;
char c;
};

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 94


SIS 2210 “METODOLOGIA DE LA PROGRAMACION II

El tipo de dato ‘bloque’ contiene tres miembros a,b y c, el tamaño de este tipo de
dato es equivalente al tamaño del miembro ‘b’, es decir 4 bytes.

b) Declaración de una variable unión.

 A partir de un tipo de dato

Unión bloque pb;

La variable ‘pb’ es del tipo unión bloque y puede almacenar uno de los tres valores
que corresponde a uno de los campos.

 Solo la variable.

union
{
int a;
float b;
char c;
} pq;

La variable ‘pq’ es una variable unión con similares características a la variable ‘pb’.

El acceso a los campos de una ‘union’ es similar al de una estructura, sin embargo se debe
tomar en cuenta que en una ‘union’ solo se puede almacenar el valor de uno de los campos
en un momento dado.

M.Cs. Ing. Julio Cesar Bermudez Vargas Página 95

S-ar putea să vă placă și