13.01.2015 Views

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 148 — #186<br />

✐<br />

Capítulo 4. Abstracción de Datos<br />

tablem<strong>en</strong>te el usuario no siempre se preguntará si la inicialización y el limpiado de<br />

los objetos son obligatorios. Ellos le darán importancia a lo que ellos quier<strong>en</strong> hacer<br />

y no nos darán tanta importancia a nosotros (el programador de la librería) cuando<br />

les digamos «¡Hey! ¡espera un poco! ¡Debes hacer esto primero!». Otro problema que<br />

puede pres<strong>en</strong>tarse es el hecho de que algunos usuarios quieran inicializar los elem<strong>en</strong>tos<br />

(datos internos) de una estructura por su cu<strong>en</strong>ta. En C no hay un mecanismo<br />

para prev<strong>en</strong>ir este tipo de conductas (más presagios de los temás que v<strong>en</strong>drán...).<br />

La intStash se va ll<strong>en</strong>ando con <strong>en</strong>teros mi<strong>en</strong>tras que el stringStash se va<br />

ll<strong>en</strong>ando con arrays de caracteres. Estos arrays de caracteres son producidos ley<strong>en</strong>do<br />

el archivo fu<strong>en</strong>te CLibTest.cpp y almac<strong>en</strong>ando las líneas de este archivo <strong>en</strong><br />

el string line. Obt<strong>en</strong>emos la repres<strong>en</strong>tación «puntero a carácter» de line con el<br />

método c_str().<br />

Una vez cargados los Stash ambos se muestran <strong>en</strong> pantalla. intStash se imprime<br />

usando un bucle for <strong>en</strong> el cual se usa count() para determinar la cantidad de<br />

elem<strong>en</strong>tos. El stringStash se muestra utilizando un bucle while d<strong>en</strong>tro del cual<br />

se va llamando a fetch(). Cuando esta función devuelve cero se rompe el bucle ya<br />

que esto significará que se han sobrepasado los límites de la estructura.<br />

El lector también pudo haber visto un molde adicional <strong>en</strong> la línea:<br />

cp = (char*)fetch(&stringStash, i++)<br />

Esto se debe a la comprobación estricta de tipos <strong>en</strong> <strong>C++</strong>, que no permite asignar<br />

un void * a una variable de cualquier tipo, mi<strong>en</strong>tras que C sí lo hubiera permitido.<br />

4.1.2. Malas suposiciones<br />

Antes de abordar los problemas g<strong>en</strong>erales de la creación de una librería C, discutiremos<br />

otro asunto importante que se debe t<strong>en</strong>er claro. Fíjese que el archivo de<br />

cabecera CLib.h debe incluirse <strong>en</strong> cada archivo fu<strong>en</strong>te que haga refer<strong>en</strong>cia al tipo<br />

CStash ya que el compilador no puede adivinar qué aspecto ti<strong>en</strong>e la estructura. Sin<br />

embargo, sí puede adivinar el aspecto de una función. Aunque eso pueda parecer<br />

una v<strong>en</strong>taja, veremos que <strong>en</strong> realidad, es un grave problema de C.<br />

Aunque siempre debería declarar las funciones incluy<strong>en</strong>do un archivo de cabecera,<br />

<strong>en</strong> C las declaraciones de funciones no son es<strong>en</strong>ciales. En este l<strong>en</strong>guaje (pero no<br />

<strong>en</strong> <strong>C++</strong>), es posible llamar a una función que no ha sido declarada. Un bu<strong>en</strong> compilador<br />

seguram<strong>en</strong>te avisará de que deberíamos declarar la función antes de usarla,<br />

pero nos permitirá seguir dado que no es obligatorio hacerlo <strong>en</strong> C estándar. Esta es<br />

una práctica peligrosa ya que el compilador puede asumir que una función que ha<br />

sido llamada con un int como argum<strong>en</strong>to, t<strong>en</strong>ga un int como argum<strong>en</strong>to cuando, <strong>en</strong><br />

realidad, es un float. Como veremos, esto puede producir errores que pued<strong>en</strong> ser<br />

muy difíciles de depurar.<br />

Se dice que cada archivo de implem<strong>en</strong>tación C (los archivos de ext<strong>en</strong>sión .c) es<br />

una unidad de traducción (translation unit). El compilador se ejecuta indep<strong>en</strong>di<strong>en</strong>tem<strong>en</strong>te<br />

sobre cada unidad de traducción ocupándose, <strong>en</strong> ese mom<strong>en</strong>to, solam<strong>en</strong>te<br />

<strong>en</strong> ese archivo. Por eso, la información que le demos al compilador por medio de los<br />

archivos de cabecera es muy importante dado que determina la forma <strong>en</strong>q que ese<br />

archivo se relaciona con las demás partes del programa. Por eso motivo, las declaraciones<br />

<strong>en</strong> los archivos de cabecera son particularm<strong>en</strong>te importantes dado que, <strong>en</strong><br />

cada lugar que se incluy<strong>en</strong>, el compilador sabrá exactam<strong>en</strong>te qué hacer. Por ejemplo,<br />

si <strong>en</strong> un archivo de cabecera t<strong>en</strong>emos la declaración void func(float) , si<br />

148<br />

✐<br />

✐<br />

✐<br />

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!