El refinamiento descendente

La programación modular se fundamenta en la resolución de problemas complejos mediante la división de éstos en subproblemas más pequeños que se solucionan independientemente. Si todavía resultan demasiado complejos se vuelven a dividir y así sucesivamente.

Esto permite centrarse en problemas muy concretos que se pueden abordar con todo detalle.

Este método de diseñar la solución de un problema, diseñando una jerarquía de módulos y buscando las soluciones de los subproblemas que lo integran es también conocido como refinamiento descendente.

La codificación de los algoritmos que resuelven los subproblemas en lenguaje C++ se realiza mediante funciones.

El uso de funciones definidas por el programador permitirá dividir un programa grande en un cierto número de componentes más pequeños, cada uno de las cuales tiene un propósito único e identificable.

A veces no es fácil decidir exactamente cómo dividir el problema en funciones y, en ocasiones, una decisión ya tomada debe ser modificada.

../../_images/funciones1.jpg

Esquema de la programación modular

Ventajas del uso de funciones

Las funciones aportan claridad lógica al programa al descomponer éste en varias funciones concisas que resuelven partes concretas del problema global.

Muchos programas requieren la realización del mismo grupo de instrucciones desde distintas partes del programa. El uso de funciones evita repetir líneas de código de forma redundante.

Las funciones permiten construir bibliotecas (libraries), conjuntos de funciones que permiten reutilizar código.

Venimos usando de forma exhaustiva la biblioteca estándar std, con subcomponentes como iostream y cmath.

La reutilización de código permite:

  • aprovechar el trabajo de otros programadores y economizar tiempo.

  • contribuye a mejorar la legibilidad, dado que otros programadores reconocerán fácilmente la tarea que está realizando.

En C++, el código de la función es exclusivo de la función y no se puede acceder a él más que llamando a la función. Por ello, se dice que toda función esconde código.

Dado que muchas de las variables asociadas solo pueden ser modificadas accediendo a la función, esto facilita la depuración de errores. Una vez que estamos seguros de que una función hace su trabajo correctamente, podemos olvidarnos de ella a efectos de búsqueda de errores.

Otra gran ventaja del uso de funciones es que la subdivisión de un programa complejo en módulos más simples permite el desarrollo en equipo de un programa.

Funciones de biblioteca estándar

Un buen ejemplo de las ventajas de usar funciones es la existencia de la biblioteca estándar std.

La biblioteca estándar de C++ es una colección de funciones y clases que forman parte de la norma ISO del propio C++.

Esto garantiza que usando esas funciones nuestros programas son portables. Además, su implementación es muy eficiente. Por último, no necesitamos reinventar la rueda, pudiendo reutilizar código ya existente.

La biblioteca estándar está dividida a su vez en subbibliotecas, para que en cada programa utilicemos sólo las que necesitemos.

Para su uso, basta añadir al inicio del programa fuente un archivo de cabecera asociado a la biblioteca:

#include <cabecera_biblioteca>

Los archivos de cabecera son literalmente añadidos en el archivo fuente a través de la directiva #include. Esta metodología permite incorporar a las unidades de compilación, los archivos con extensión *.cpp, todos aquellos componentes de la biblioteca que permiten al compilador/enlazador generar el ejecutable.

La biblioteca iostream, que venimos usando desde el inicio del curso, nos permite usar cin y cout para operaciones de entrada y salida.

Así, sin el uso de los archivos de cabecera, en cada uno de los programas que usasen cin y/o cout, sería necesario añadir centeneras de líneas de código. Algo tedioso y carente de toda lógica.

También hemos utilizado ya funciones de la biblioteca cmath, cuyo carácter es de tipo matemático.

Ejemplos de funciones de la biblioteca cmath

Función

Descripción

double sqrt(double x);

Raíz cuadrada

double pow(double base, double exp);

Potencia

double exp(double x);

Exponencial natural

double log(double x);

Logaritmo natural

double cos(double x);

Coseno

double sin(double x);

Seno

double fabs(double x);

Valor absoluto

Un listado completo puede verse en el siguiente enlace:

https://en.cppreference.com/w/cpp/header/cmath.

Nota

Muchos de los archivos de cabecera de las bibliotecas estándar de C++ que empiezan por c, como <cmath>, son prácticamente idénticos a los de las bibliotecas del Lenguaje C que se usaban con la extensión .h, como por ejemplo, math.h.