[C con Clase] otra de clases (que pesado el tipo)

Steven Davidson steven en conclase.net
Vie Mayo 25 04:25:58 CEST 2007


Hola Rodolfo,

El pasado 2007-05-24 23:04:50, rodolfo escribió:

r> Hola a Todos.-
r> Sigo jorobando con esto de las clases;  Mi pregunta ahora es:
r> Tengo tres clases, Nombre, Estatura y Persona,
r> y la clase Persona contiene 2 variables miembro privadas de tipo Nombre y 
r> Estatura
r> Instancio:    Nombre N("Agatha");
r> Instancio:    Estatura E(1.60);
r> Instancio:    Persona P( N, E );
r> Imprimo:      P.imprimePersona();
r> Resultado:    Agatha 1.60 m
r> Cambio N:     N.estableceNombre("Maria");
r> Imprimo:      P.imprimePersona();
r> Resultado:    Agatha 1.60 m
r> Pregunta :    ¿ si cambie N, porque no cambia P, o no se espera
r>                      que asi suceda ?

Esto depende de cómo has implementado las relaciones entre las clases y por tanto los objetos que instancias. Sospecho que pasas los objetos 'N' y 'E' por copia (o por valor); algo así,

Persona::Persona( Nombre n, Estatura e )
{
  nombre = n;
  estatura = e;
}

Lo que haces es copiar los objetos pasados como parámetros.

En cuanto a la "solución", sugiero no resolverlo. En general, la POO se basa en la encapsulación de sus datos. Esto significa que cada objeto debería proteger sus propios datos de decisiones externas. El objeto en sí es quien debería realizar cualesquier cambios necesarios, típicamente por petición externa, pero el objeto es quien los realiza. En tu caso, hiciste esto a través de 'estableceNombre()', en lugar de dar acceso directo a la información del objeto.

Ahora bien, según un diseño u otro, es posible que quieras ofrecer acceso directo a ciertos datos aunque tengamos menor protección. Para esto, podemos ofrecer funciones miembros que retornen una referencia a ciertos datos, para que el exterior los acceda y posiblemente modifique directamente. Por ejemplo,

class Persona
{
private:
  Nombre nombre;
  Estatura estatura;

public:
  Nombre &obtener_nombre()  { return nombre; }
  Estatura &obtener_estatura()  { return estatura; }
};

Con estas funciones, podemos modificar el nombre y estatura de cualquier objeto 'Persona'. Tomando tu ejemplo,

P.obtener_nombre().estableceNombre( "Maria" );
P.imprimePersona();

Como podemos ver, formamos una encadenación para ir manipulando la información que obtenemos.


Otra solución a tu problema es ser más directos, pero que puede traer más problemas. Esto consiste en usar punteros. Por ejemplo,

class Persona
{
private:
  Nombre *pNombre;
  Estatura *pEstatura;

public:
  Persona( Nombre *pNom, Estatura *pEst ) : pNombre(pNom), pEstatura(pEst)  {}
};

Persona P( &N, &M );

Con este diseño, tu código funcionaría como deseas, pero esto rompe el objetivo de la encapsulación. Esto es porque cualquier código foráneo a un objeto 'Persona' puede acceder y modificar la información a través de los objetos de 'Nombre' y de 'Estatura'. Las modificaciones a un objeto repercuten automáticamente al estado de otro, sin restricción ni control de tal objeto asociado.

Si estás aprendiendo POO, no aconsejo implementar esta solución. Existen casos en los que sí haríamos algo parecido a lo anterior, pero deberías tener buenos motivos para hacerlo.


Espero haber aclarado la duda.

Steven


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