[C con Clase] Duda sobre ejemplo de la sección

Steven Davidson steven en conclase.net
Sab Ene 20 21:28:45 CET 2007


Hola Sorcerer,

El pasado 2007-01-20 05:12:14, Sorcerer escribió:

S> Gracias por la explicación, me aclaro bastante pero me generó una nueva duda :S
S> Voy a ir explicando lo q pienso entre medio xq creo que así es más fácil ver si entendí algo mal.

Muy bien.

S> Cuando hacen:
S> > Persona *Carlos = new Empleado("Carlos");
S> > Gente[0] = Carlos->Clonar();
S> "Carlos" es un objeto de tipo Empleado, aunque el puntero apunte hacia un objeto de tipo Persona. Así es, ¿cierto? :S

Creo que lo entiendes, pero voy a reformular lo que has dicho:

'Carlos' es un puntero a 'Persona'. Se instancia dinámicamente un objeto polimórfico de tipo 'Empleado'. Este objeto es apuntado por 'Carlos'.

S> Entonces, le sigo la pista al objeto para ver que hace la función clonar de la class Empleado (xq el objeto era de ese tipo y la función clonar es virtual):

Hasta aquí, bien.

S> > virtual Persona* Clonar() { return new Empleado(*this); }
S> Como usan new, crean un objeto nuevo. Ese nuevo objeto es de tipo Empleado y la idea es que sea una copia del objeto que se esta trabajando en ese momento, xq usan el puntero this. Ya... entonces ahora me voy al constructor de la class Empleado, que eso es lo que se esta llamando y le pasan como parámetro *this:

Correcto.

S> > Empleado::Empleado(const Empleado &e) : Persona(e) {
S> >   cout << "Emp: constructor copia." << endl;
S> > }
S> Y he aquí mi gran duda: En este constructor lo que hacen es... ¿ Llamar al constructor de Persona (con Persona(e)) ?. Porque en este caso, "e" es una 

Sí. Llamamos primero al constructor de 'Persona' antes de ejecutar las sentencias del constructor copia de 'Empleado'.

referencia a un objeto de tipo Empleado, sin embargo el constructor de la class Persona es:
S> > Persona::Persona(const Persona &p) {
S> >   strcpy(nombre, p.nombre);
S> >   cout << "Per: constructor copia." << endl;
S> > }
S> Y este constructor trabaja con un objeto de tipo Persona, no de tipo Empleado... que es el tipo que le estamos pasando :S

Sí. Esto es una consecuencia de la herencia. Un objeto de una clase derivada _ES_ un objeto de sus clases bases; obviamente, no en su totalidad. Por ejemplo,

class Base {...};
class Der : public Base {...};
...
Base o_base;
Der o_der;

Base &ref = static_cast< Base >( o_der );  // Debido a herencia: Der _ES_ Base


Esto es correcto, ya que 'Der' hereda de 'Base' y por tanto podemos afirmar que un objeto 'Der' es un objeto 'Base'. La afirmación inversa no es correcta; o sea, un objeto 'Base' no es un objeto 'Der'.

Obviamente, la referencia 'ref' maneja un objeto de tipo 'Base', irrelevantemente si originalmente ese objeto fuese de tipo 'Der'. Para que cambie de tipo implícitamente, necesitamos el mecanismo de polimorfismo. La herencia nos ayuda, pero para que se escoja las versiones originales de las funciones miembros y para que se "acuerde" del tipo original, precisamos de polimorfismo.

S> No se si le seguí mal la pista al objeto y por eso llegué a esto, sino... entonces no entiendo la idea de crear una función virtual para llamar al constructor correcto, si al final le pasamos un objeto de cualquier tipo al constructor copia de Persona y lo trabajamos como si fuera de tipo Persona :S

No. Lo hiciste bien.


Espero haber aclarado el tema.

Steven


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