[C con Clase] Dudas sobre clases

Steven Richard Davidson stevenrichard.davidson en gmail.com
Jue Dic 13 13:29:37 CET 2007


Hola Patricio,

On Dec 13, 2007 12:42 PM, Patricio González Sevilla <pignium en hotmail.com> wrote:
>
> En el Curso de C++.
>
> Capítulo 29 - CONSTRUCTORES tengo algunas dudas:
>

Muy bien. Veamos las dudas que tienes.

> - ¿Qué ventajas posee ubicar la definición de las funciones de las clases
> fuera de la declaración de la clase? ¿Es lo habitual?
>

La práctica de separar las declaraciones de sus definiciones suele ser
por organizar el código fuente. Existen otras ventajas de hacer esto,
como es la posibilidad de crear una biblioteca estática o incluso
dinámica. De esta manera, ya tenemos las declaraciones separadas y
preparadas para el compilador. Otra posible ventaja por la
organización es que podemos modificar las definiciones o
implementaciones sin tener que cambiar todo el proyecto ni recompilar
todos los demás ficheros fuentes; sólo aquél que fue modificado.

Cuando llegues al capítulo 40 del curso, verás cómo definir y usar
plantillas (templates, en inglés). Una de las características de las
plantillas es que no se puede separar las declaraciones de sus
implementaciones en diferentes unidades de traducción.

Como puedes ver (o verás), no siempre podemos hacer la separación.

> Capítulo 30 - DESTRUCTORES tengo algunas dudas:
>
> - Si cad está declarada como miembro privado, ¿Es correcto acceder a ella de
> esta forma al crear el constructor copia?:
> cadena::cadena(const cadena &Cad) {
>  // Reservamos memoria para la nueva y la almacenamos
>  cad = new char[strlen(Cad.cad)+1];
>  // Reserva memoria para cadena
>  strcpy(cad, Cad.cad); // Almacena la cadena
>  // ¿No debería accederse a Cad.cad con el método [char *cadena::Leer(char
> *c)]?
> }

Podríamos invocar 'cadena::Leer()', como sugieres, pero esto supone un
coste añadido en la ejecución. De todas maneras, a veces sí se usan
sus propias funciones miembros por motivos de diseño.

En cuanto al acceso a 'cad' a través del objeto 'Cad', esto sí es
posible. Ten presente que los modificadores de acceso se aplican a la
clase y no a los objetos directamente. Esto significa que una vez que
estemos en el ámbito de la clase, tenemos acceso a todos los miembros
de tal clase, irrelevantemente de los objetos de tal clase. Puedes
pensar que estamos manejando miembros a nivel de clases y no a nivel
de objetos. Como estamos en el ámbito de clases, el acceso es el mismo
para cualesquier objetos de tal clase.

> - Otra duda en este apartado es el siguiente. ¿Este método:
>
> char *cadena::Leer(char *c) {
>  strcpy(c, cad);
>  return c;
> }
> no podría sustituirse por:
>
> char *cadena::Leer() {
>  char *c;
>  strcpy(c, cad);
>  return c;
> }
> ?.
>

No. En la primera versión, 'c' apunta a una cadena de caracteres
existente, mientras que en la segunda versión 'c' es un puntero
arbitrario, ya que ni siquiera fue inicializado. En la segunda versión
de 'cadena::Leer()', 'c' no apunta a ninguna dirección de memoria
conocida y por tanto, puede ser inválida. Al intentar escribir
caracteres a partir de tal dirección desconocida, posiblemente
estaríamos sobrescribiendo otros datos pertenecientes a otros
programas. Bajo ciertos sistemas operativos que protegen las
aplicaciones y detienen este tipo de operaciones que salen fuera de
sus limitaciones, obtendríamos mensajes de errores.

Una posible solución a tu versión es crear memoria dinámicamente
dentro de la función miembro. Por ejemplo,

char *cadena::Leer()
{
  return strcpy( new char[ strlen(cad) ], cad );
}

El problema es que hay muchas tareas costosas que posiblemente no
queramos. De todas maneras, esto es una cuestión de diseño. Si
queremos ofrecer una función rápida de acceso, entonces optaríamos por
la versión original de 'cadena::Leer()'. Si por otro lado, queremos
ofrecer una duplicación de la cadena sin que el programador tenga que
hacer mucho por su parte, entonces optaríamos por esta versión de
'cadena::Leer()'.

En general, no es buen diseño crear memoria internamente y dejar al
programador preocuparse por su liberación (o destrucción). En este
caso, no es del todo claro que el programador tenga que hacer algún
mantenimiento.


Espero haber aclarado las dudas.

Steven




Más información sobre la lista de distribución Cconclase