Está en la página 1de 15

APUNTES DE C+-

UNED - Fundamentos de Programación

http://shutdown.systemfault.org
shutdown(arroba)systemfault(punto)org

Apuntes de la asignatura Fundamentos de Programación, de 1º de Grado en


Tecnologías de la información de la UNED. Están sacados del libro de la
bibliografía básica para el curso 2010/2011 “Fundamentos de
Programación” de Cerrada Somolinos y Collado Machuca.

TIPOS DE DAT0
int – Tipo número entero.
float – Tipo número decimal de precisión normal.
double – Tipo número decimal de doble precisión.
Char – Tipo carácter.

CARACTERES DE CONTROL
'\n' – Salto de línea.
'\r' – Retorno al comienzo de la línea.
'\t' – Tabulación.
'\'' - Apóstrofe.
'\\' - Barra inclinada.
'\f' – Salto de página, borrado de pantalla.

LIBRERÍAS
ctype.h

bool isalpha(char c) – Indica si 'c' es una letra.

bool isascii(char c) – Indica si 'c' es un carácter ASCII.

bool isblank(char c) - Indica si 'c' es un carácter de espacio o


tabulación.

bool iscntrl(char cc) – Indica si 'c' es un carácter de control.

bool isdigit(char c) – Indica si 'c' es un dígito decimal (0-9).

bool isspace(char c) – Indica si 'c' es espacio en blanco o salto.

bool islower(c) – Indica si 'c' es una letra minúscula.

bool isupper(char c) – Indica si 'c' es una letra mayúscula.

char tolower(char c) – Devuelve la minúscula de 'c'.

char toupper(char c) – Devuelve la mayúscula de 'c'.

stdio.h

printf(char*formato[,argumento,...]) - Escribe datos en salida


estándar. (%c Caracter %d Entero %e Real (double o float),
notacion cientifica. %f Coma flotante %s Cadena de caracteres %x
Hexadecimal sin signo).
scanf(char*formato [,direccion,...]) - Lee datos en dispositivo de
entrada. (%c Caracter %d Entero %x Hexadecimal %i Entero
Decimal %f Numero Real %o Octal %p Puntero %s Cadena).

putc(c, f) – Escribre un carácter en el archivo f.

putchar(c) – Escribe un carácter en el dispositivo de salida.

gets() – Lee una cadena de caracteres desde la entrada estándar.

Getchar() - Lee un carácter desde la entrada estándar.

string.h

strcmp(s1, s2) – Compara dos cadenas de caracteres lexicograficamente.


Devuelve un valor negativo si s1 < s2; 0 si s1 y s2 son
identicas; y un valor positivo si s1 > s2.

strcmpi(s1, s2) - Compara dos cadenas de caracteres lexicograficamente,


sin diferenciar mayusculas de minusculas. Devuelve un valor
negativo si s1 < s2; 0 si s1 y s2 son identicas; y un valor
positivo si s1 > s2.

strcpy(s1, s2) - Copia la cadena de caracteres s2 en la cadena s1.

strlen(s) - Devuelve el numero de caracteres de la cadena 's'.

system(s) - Pasa la orden 's' al sistema operativo. Devuelve cero si la


orden se ejecuta correctamente; en otro caso devuelve un valor
distinto de cero, tipicamente -1.

math.h

float sqrt(float x) – Devuelve la raiz cuadrada de 'x'.

float pow(float x, float y) - Devuelve 'x' elevado a 'y'.

float exp(float x) – Devuelve 'e' elevado a 'x'.

float log(float x) – Devuelve logaritmo neperiano de 'x'.

float sin(float x) – Seno de 'x'.

float cos(float x) – Coseno de 'x'.

float tan(float x) – Tangente de 'x'.

float atan(float x) – Arcotangente de 'x'.

float round(float x) – Valor de 'x' redondeado a entero.

FUNCIONES Y PROCEDIMIENTOS
Las funciones siempre retornan un valor que coincide en tipo con el
declarado en la interfaz de la función. Un procediento no tiene como
objetivo, en general, devolver un valor obtenido por cálculo.

Función:
tipo_Resultado nombre_funcion(argumentos) {
sentencias;
return ...;
}

Procedimiento:

void nombre_procedimiento(argumentos) {
sentencias;
}

ESTRUCTURAS
SELECCION:

if (condición) {
acción;
} else if (condición) {
acción;
} else {
acción;
}

switch (expresión) {
case valor:
acción;
break;
case valor:
acción;
break;
…..................
default:
acción;
}

BUCLE:

while (condición) {
acción;
}

do {
acción;
} while (condición);

for (int indice = valor_inicial; indice <= valor_final; indice++) {


acción;
}

continue

La sentencia continue dentro de cualquier bucle finaliza la iteración


en curso e inicia la siguiente.

TRATAMIENTO DE EXCEPCIONES
throw – Provoca la terminación del subprograma; semejante a return.

try – Agrupa el bloque de código en el que se programa el algoritmo del


problema a resolver sin tener en cuenta excepciones.
catch – Agrupa el código para el tratamiento de la excepción. Se tienen
que programar sentencias catch para todos las posibles excepciones del
bloque try.

DEFINICIÓN DE TIPOS
TIPO SINÓNIMO

typedef tipo_definido tipo_nuevo;

typedef int TipoEdad;

TIPO ENUMERADO

typedef enum Nombre_tipo { lista de valores};

typedef enum Tipo_dia {lunes, martes, miércoles, jueves, viernes};

Es un tipo ordinal, se puede usar int(valor) y tipo_enumerado(int):

int(lunes) == 0;
Tipo_dia(1) == martes;

TIPO PREDEFINIDO BOOL

typedef enum bool {false, true};

int false == 0;
int true == 1;

TIPO VECTOR (array)

typedef TipoElemento TipoVector[número_elementos];

typedef int TipoVector[10];

typedef enum Colores {rojo, blanco, negro};


typedef Colores Tipo_colores[5];

const int numero_letras = 9;


typedef char Tipo_cadena[numero_letras];

Para usar los tipos de dato hay que declarar variables de dichos tipos;
se pueden inicializar durante la declaración:

Tipo_colores paleta = {rojo, rojo, blanco, negro, blanco};

Las operaciones con vectores se hacen operando con sus elementos uno
por uno:

paleta[0] = rojo;

Para copiar dos vectores se puede programar un bucle que realice la


copia elemento a elemento:

for (int i=0; i < número_elementos; i++) {


vector1[i] = vector2[i];
}

El modo por defecto de paso de argumentos del tipo vector es por


referencia:
void LeerVector(Tipo_vector vector);

Para pasarlo por valor, el tipo debe ir precedido de la palabra


reservada const, (la ejecución del procedimiento no modifica la
variable vector):

void LeerVector(const Tipo_vector vector);

VECTOR DE CARACTERES (string)

typedef char Nombre[número_elementos];

Se reserva espacio al final de la cadena para el carácter nulo (\0).

typedef char Cadena10[11];


No es posible la asignación directa entre dos variables de tipo cadena;
se puede programar un bucle para hacerlo elemento a elemento o
directamente tirar de strcpy, (<string.h>), que copia una cadena en
otra:

Cadena10 nombre, apellido;


nombre = “Ricardito”;
strcpy(apellido, nombre);

TIPO REGISTRO (struct)

typedef struct Tipo_registro {


tipo_campo nombre_campo;
tipo_campo nombre_campo;
….......................
}

typedef enum Meses {Enero, Febrero, ...};


typedef struct Tipo_Fecha {
int dia;
meses mes;
int anno;
};

Tipo_Fecha hoy;
Tipo_Fecha ayer = {2, Enero, 2011);
hoy.dia = 1;
hoy.mes = Febrero;
hoy.anno = 2011;

ESTRUCTURAS DE DATOS
VECTOR ABIERTO

void EscribirVectorAbierto(const tipo_dato vector[], int


numero_elementos) {
for (int i=0; i<numero_elementos; i++) {
…..............................
}
}

En el caso de los vectores abiertos de caracteres, no es necesario


indicar el número de elementos en los argumentos, se usa el carácter
nulo del final de la cadena:

void AnalizarTexto(const char texto[]) {


…................................
}
AnalizarTexto(“esto es el texto”);

FORMACIONES ANIDADAS. MATRICES

Son estructuras de tipo formación (array) de dos o más dimensiones.

typedef TipoElemento TipoMatriz[NumFilas][NumColumnas];


TipoMatriz matriz;

No se puede definir una matriz de tipo abierto; sin embargo, sí que se


puede definir una matriz cuyos elementos sean un vector abierto, pero
de una sola dimensión.

TIPO UNIÓN

Una colección de campos alternativos, cada dato particular sólo usará


uno de esos campos en un momento dado. La definición es similar al
struc, con la diferencia de que se usa la palabra union.

typedef struct TipoFraccion {


int numerador;
int denominador;
};

typedef union TipoNumero {


int valorEntero;
int valorReal;
TipoFraccion valorRacional;
};

TipoNumero numero1, numero2;


numero1.valorEntero = 10;
numero1.valorReal = float(numero1.valorEntero);
numero1.valorRacional.numerador = 10;
numero1.valorRacional.denominador = 1;
numero2.valorRacional.numerador = numero1.valorRacional.numerador;

REGISTROS CON VARIANTES

Registros en los que hay una colección de campos fijos aplicables en


todos los casos y campos variantes que se definen según el esquema
unión. Se reserva un campo fijo (discriminante) para indicar cuál es la
variante aplicable en cada caso.

typedef enum ClaseNumero {Entero, Real, Fraccion};

typedef struct TipoFraccion {


int numerador;
int denominador;
};

typedef union TipoValor {


int valorEntero;
float valorReal;
TipoFraccion valorRacional;
};

typedef struct TipoNumero {


ClaseNumero clase; /* discriminante */
TipoValor valor;
};
void EscribirNumero(TipoNumero n) {
switch (n.clase) {
case Entero:
printf(“%d”, n.valor.valorEntero);
break;
case Real:
printf(“%f”, n.valor.valorReal);
break;
….........................
}

TABLAS

Una formación simple de registros. Son el fundamento de las bases de


datos relacionales.

typedef enum TipoProvincia {


Nulo, Alava, Albacete, …., Zaragoza
};

const int MaxProvincias = int(Zaragoza);


typedef char Tiposiglas[2];
typedef char TipoNombre[30];

typedef struct TipoDatosProvincia {


TipoSiglas siglas;
TipoNombre nombre;
int codigo;
};

typedef TipoDatosProvincia TipoTablaProvincias[MaxProvincias+1];


TipoTablaProvincias provincias;

provincias[Cadiz].siglas[0] = 'C';
provincias[Cadiz].siglas[1] = 'A';
strcpy(provincias[Cadiz].nombre = “Cádiz”;
provincias[Cadiz].codigo = 11;

ESQUEMAS DE DATOS Y ESQUEMAS DE ACCIONES

Tupla – Secuencia
Union – Selección
Formación – Iteración

Podemos combinar las diferentes estructuras de datos haciendo que los


elementos de una estructura sean, a su vez, otras estructuras, sin
limitación en la profundidad de anidamiento.

ESQUEMAS TÍPICOS DE OPERACIÓN CON FORMACIONES


ESQUEMA DE RECORRIDO

Consiste en realizar una operación con todos y cada uno de los


elementos de una formación.

/* Halla el máximo en un vector de enteros */


float Maximo(const float v[], int N) {
float max;
for (int i=0; i<N; i++) {
if (i== 0 || v[i]>max) {
max = v[i];
}
}
return max;
}

RECORRIDO DE MATRICES

Se usan tantos for anidados como dimensiones tenga la formación.

/* Escribe los elementos de una matriz por filas */


const int N = …;
const int M = …;
typedef int TipoMatriz[N][M];
TipoMatriz matriz;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
printf(“%5d”, matriz[i][j];
}
printf(“\n”);
}

BÚSQUEDA SECUENCIAL

Se examinan uno a uno los elementos de una formación para tratar de


localizar los que cumplen una condición.

/* Halla el número de veces que aparece un elemento en una formación */


typedef … TipoElemento …;
int Nveces(TipoElemento buscado, const Tipoelemento v[], int N) {
int veces = 0;
for (int i=0; i<N; i++) {
if (v[i] == buscado) {
veces++;
}
}
return veces;
}

INSERCIÓN

Insertar un nuevo elemento en una colección de elementos ordenados,


manteniendo el orden de la colección.

/* Inserta un elemento en un vector de elementos ordenados. Se supone


que los elementos almacenados ocupan las posiciones desde el principio
y que hay espacio libre al final del vector */
typedef … TipoElemento …;
void Insertar(TipoElemento v[], int N, TipoElemento elemento) {
int j = N;
while (j>0 && elemento<v[j-1]) {
v[j] = v[j-1];
j--;
}
v[j] = elemento;
}

ORDENACIÓN POR INSERCIÓN DIRECTA

/* Basado en el esquema anterior, ordena los datos almacenados en un


vector. El primer elemento ya está ordenado, extraemos el segundo
elemento y deja un hueco, se inserta el elemento extraido en el hueco
correspondiente entre los elementos ya ordenados */
typedef … TipoElemento …;
void Ordenar(TipoElemento v[], int N) {
TipoElemento valor;
int j;
for (int i=1; i<N; i++) {
valor 0 v[i];
j = i;
while (j>0 && valor<v[j-1]) {
v[j] 0 v[j-1];
j--;
}
v[j] = valor;
}
}

BÚSQUEDA POR DICOTOMÍA

Se usa con datos ordenados. Comparamos el elemento a buscar con el que


está justo en la mitad del vector, se comprueba si coincide y, si no,
si continúa la búsqueda a la izquierda o a la derecha, así
sucesivamente. Finaliza cuando se encuentra el elemento o ya no quedan
elementos por analizar.

/* Busca un valor en un vector */


typedef … TipoElemento …;
int Indice(TipoElemento buscado, const Tipoelemento v[], int N) {
int izq, dch, mitad, pos;
izq = 0; dch = N-1; pos 0 -1;
while (pos<0 && izq>=dch) {
mitad = (izq+dch)/2;
if (v[mitad] == buscado) {
pos = mitad;
} else if (v[mitad] < buscado) {
dch = mitad-1;
} else {
izq 0 mitad+1;
}
}
return pos;
}

TÉCNICA DEL CENTINELA

Se usa para simplificar las condiciones de contorno; evita la necesidad


de detectar de manera explícita si se ha llegado a un elemento del
contorno y/o realizar con él un tratamiento especial. Garantizamos que
el dato buscado estará en el vector incluyéndolo al final del mismo,
así no es necesario comprobar que se ha alcanzado el final del vector.

/* Busca un elemento, devuelve -1 si el elemento no se encuentra */


typedef … TipoElemento …;
int Indice(TipoElemento buscado, const TipoElemento v[], int N) {
int pos 0 0;
v[N] = buscado; /* centinela */
while (v[pos] != buscado) {
pos++;
}
if (pos>=N) {
pos = -1;
}
return pos;
}

MATRICES ORLADAS
Estas matrices se dimensionan con dos culumnas y dos filas más de las
necesarias, garantizando que todos los elementos de contorno de la
matriz original tienen elementos vecinos en todas direcciones. Antes de
operar, se inicializan las filas y columnas extras con un valor de
contorno (centinela).

PUNTEROS Y VARIABLES DINÁMICAS

Estructuras dinámicas son aquellas que pueden modificar su tamaño en


función de los datos particulares que se estén manejando en cada
ejecución. Su capacidad no podrá exceder de la capacidad de la máquina
en la que se esté corriendo el programa.

LA ESTRUCTURA SECUENCIA

Es un esquema de datos de tipo iterativo con un número variable de


elementos.

- Operaciones de construcción:
Añadir o retirar componentes al principio de la secuencia.
Añadir o retirar componentes al final de la secuencia.
Añadir o retirar componentes en posiciones intermedias.

- Operaciones de acceso:
Acceso secuencial: Los componentes se tratan uno por uno, en el
orden en que aparecen en la secuencia.
Acceso directo: Se accede a cualquier componente indicando su
posición.

El tratamiento de una secuencia se realiza empleando una variable que


señala a un elemento de la secuencia (cursor).

VARIABLES DINÁMICAS

Una variable dinámica no se declara como tal, se crea en el momento


necesario y se destruye cuando ya no se necesita. No tienen nombre, se
designan mediante otras variables llamadas punteros o referencias. Una
vez creadas, siguen existiendo hasta que se indique explicitamente que
ya no son necesarias.

PUNTEROS

Son variables simples cuyo contenido es una referencia a otra variable.


Su valor no es representable como número o texto. El tipo de un puntero
especifica el tipo de variable al que puede apuntar. Una vez declarado
el tipo se definen variables puntero de dicho tipo. Un puntero puede
pasarse como argumento a un subprograma, tanto por valor como por
referencia.

typedef int* TipoEntero;


TipoEntero pu;
*pu = 33;
printf(“%d”, *pu);

El valor especial NULL es compatible con cualquier tipo de puntero e


indica que el puntero no señala a ninguna parte; normalmente se usa
para inicializar las variables de tipo puntero al principio del
programa, (no es automática).

USO DE VARIABLES DINÁMICAS

Las variables dinámicas se crean mediante el operador new, que crea una
variable dinámica del tipo indicado y devuelve una referencia que puede
asignarse a un puntero compatible. El valor anterior del puntero se
pierde:

typedef Tipo_variable* Tipo_puntero;


Tipo_puntero puntero;
puntero = new Tipo_variable;

Para eliminar la variable dinámica a la que señala el puntero empleamos


la sentencia delete, (no garantiza que el puntero tome el valor NULL):

delete puntero;

Una variable dinámica puede estar referenciada por más de un puntero:

typedef int* TipoEntero;


TipoEntero p1, p2;
p1 = new int;
p2 = p1;

SECUENCIAS MEDIANTE PUNTEROS

La definición simbólica de una estructura ilimitada basándose en


esquemas con un número fijo de elementos será recursiva.
En el siguiente ejemplo, cada elemento de la secuencia contiene un
registro con dos campos; el primero contiene un valor y el segundo es
un puntero que señala al siguiente campo. La secuencia completa es
accesible a través de un puntero.

typedef struct TipoNodo {


TipoComponente primero;
TipoNodo * resto;
};

typedef TipoNodo * TipoSecuencia;

TipoComponente valor;
TipoSecuencia secuencia, siguiente;

if (secuencia != NULL) {
(*secuencia).primero = valor;
siguiente = (*secuencia).resto;
}

OPERACIONES CON SECUENCIAS ENLAZADAS

/* Definición de secuencia enlazada */


typedef struct TipoNodo {
int valor;
TipoNodo * siguiente;
}

typedef TipoNodo * TipoSecuencia;


TipoSecuencia secuencia;

RECORRIDO:
Se consigue mediante un bucle de acceso a elementos y avance del
cursor. Como el número de elementos es indefinido, no se usará un bucle
con contador.

typedef TipoNodo * TipoPuntoNodo;


TipoPuntoNodo cursor;

cursor = secuencia;
while (cursor != NULL) {
printf(“%d”, cursor->valor);
cursor = cursor->siguiente;
}

BÚSQUEDA:
Se añade a la condición de terminación del bucle que se encuentre el
elemento buscado.

/* Búsqueda de la posición en la que ha de insertarse un nuevo número


en una secuencia ordenada */
int numero; /* valor a buscar */
TipoPuntoNodo cursor, anterior;
cursor = frecuencia;
anterior = NULL;
while (cursor != NULL; && cursor->valor < numero) {
anterior = cursor;
cursor = cursor->siguiente;
}

INSERCIÓN:
Se consigue creando una variable dinámica para contener el elemento a
insertar y modificando los punteros para enlazar dicha variable dentro
de la secuencia.

int numero; /* valor a insertar */


TipoPuntoNodo cursor, anterior, nuevo;
nuevo = new TipoNodo;
nuevo->valor = numero;
nuevo->siguiente = anterior->siguiente;
anterior->siguiente = nuevo;

BORRADO:
Para borrar un elemento hay que quitar el nodo que lo contiene.

TipoPuntoNodo cursor, anterior;


anterior->siguiente = cursor->siguiente;
delete cursor;
cursor = NULL;

PASO ARGUMENTOS COMO PUNTEROS

El paso por valor de un puntero equivale al pase por referencia de la


variable apuntada.

typedef int* TipoEntero;

void Imprimir(int valor) { /* paso por valor */


printf(“%d”, valor);
}

void Incrementar(TipoEntero valor) { /* paso por referencia */


*valor = *valor +1;
}

TipoEntero p1;
p1 = new int;

Imprimir(*p1);
Incrementar(p1);

TIPOS ABSTRACTOS DE DATOS


Un tipo abstracto de datos (TAD) es una agrupación de una colección de
valores y una colección de operaciones de manipulación.Se definen como
registros (struct), en los que los campos de datos sirven para
almacenar el contenido del dato abstracto y los subprogramas permiten
operar con dichos datos. La posibilidad de declarar determinados
elementos como privados permite ocultar detalles de implementación y
dejar visible sólo la interfaz del dato abstracto. Los subprogramas se
declaran por su cabecera.

/* Ejemplo de declaración de TAD */


typedef struct TipoPunto {
float x;
float y;

void Leer();
void Escribir();
float Distancia(TipoPunto p);
}

La implementación de las operaciones se hace fuera del tipo registro,


usando la notación Tipo::Operación como nombre del subprograma:

#include <stdio.h>
#include <math.h>

/* Leer un punto x.y */


void TipoPunto::Leer() {
…...............
}

/* Escribir un punto con formato x.y */


void TipoPunto::Escribir() {
…................
}

/* Calcular la distacia entre dos puntos */


float TipoPunto::Distancia(TipoPunto p) {
….................
return …;
}

La notación para referirse a las operaciones es mediante un punto,


igual que para los campos de datos:

variable.campo
variable.operacion(argumentos)

Para mantener los detalles de implementación invisibles se da la


posibilidad de declarar ciertos elementos componentes como privados
dentro del TAD, usando la palabra clave private.

Podemos aplicar la metodología de desarrollo de programas por


refinamiento basado en abstracciones usando los TAD, se siguen los
siguientes pasos:

– Considerar el dato como elemental y usar un tipo predefinido para


representarlo.
– Considerar el dato como complejo y descomponerlo en otros más
sencillos.
– Considerar el dato como abstracto y especificar su interfaz, dejando
para más adelante los detalles de su implementación.
MÓDULOS

Un módulo es un fragmento de programa desarrollado de forma


independiente; debe definir un elemento abstracto y debe ser usado
desde fuera con sólo saber qué hace (no se necesita saber cómo lo
hace). La independencia entre módulos dentro de un programa se analiza
según dos criterios:

– Acoplamiento: Indica cuántos elementos distintos de uno o varios


módulos han de ser tenidos en cuenta al usar un múdulo desde otro. Debe
ser mínimo.
– Cohesión: Indica el grado de relación que existe entre los distintos
elementos de un mismo módulo, debe ser máximo.

Cuando se descompone un programa en varios módulos, uno de ellos ha de


ser el módulo principal y ha de contener la función main().Para los
módulos no principales hay que distinguir entre elementos públicos y
privados, escribiendo el código del módulo en dos ficheros, el de
interfaz y el de implementación.

Las siguientes reglas son de obligado cumplimiento en el uso de


módulos:

– El fichero del módulo principal debe tener el mismo nombre que el


programa ejecutable final.
– Por cada módulo no principal tiene que haber dos fuentes, uno del
interfaz y otro de la implementación.
– Cada fichero de interfaz de un módulo no principal debe comenzar con
la directiva #pragma once.
– Las constantes y tipos públicos de un módulo deben declararse
solamente en el fichero de interfaz.
– Las variables y subprogramas públicos deben definirse completamente
en el fichero de implementación y además deben declararse en el fichero
interfaz.
– La declaración de cada variable pública en el fichero de interfaz
debe ir precedida de la palabra clave extern y no debe incluir
especificación del valor inicial.
– La declaración de cada subprograma público en el fichero de interfaz
consiste sólo en la cabecera (tipo, nombre y argumentos).
– La definición de cada variable global y subprograma no público en el
fichero de implementación de un módulo no principal debe ir precedida
de la palabra clave static, (esto hace que sean tratados como
identificadores locales al fichero).
– Un fichero xxx.h debe incluir otros yyy.h que use directamente.
– Un fichero xxx.cpp debe incluir su propio xxx.h y otros yyy.h que use
directamente, (aunque no hace falta hacerlo si ya los incluye su
xxx.h).

/* modulo.h */
#pragma once
typedef … TipoNuevo …;
const Tipo constante = valor;
extern Tipo variable;
Tipo Subprograma(argumentos);

/* modulo.cpp */
#include “modulo.h”
Tipo variable = valor;
Tipo Subprograma(argumentos) {
…...................
}

/* Programa principal */
#include “modulo.h”
int main() {
…............
}

Los tipos abstractos de datos y las abstracciones funcionales pueden


ser codificados como módulos independientes. Los ficheros de interfaz
contendrían la declaración de la interfaz del elemento abstracto y los
de implementación la realización del elemento.

La descomposición modular basada en abstracciones es una buena


metodología para desarrollar módulos que puedan ser reutilizados en el
futuro.Los módulos que definen abstracciones relacionadas entre sí
pueden agruparse en una biblioteca o librería para su uso posterior.

También podría gustarte