elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Los 10 CVE más críticos (peligrosos) de 2020


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  [DUDA] Polimorfismo.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [DUDA] Polimorfismo.  (Leído 2,194 veces)
Zodiak98

Desconectado Desconectado

Mensajes: 120


Ver Perfil
[DUDA] Polimorfismo.
« en: 11 Junio 2016, 01:37 am »

Buenas a todos. Necesito que me expliquen algo que me está confundiendo un poco.

Tengo un código que me he sacado de C ConClase.
El código es el siguiente.
Código
  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4.  
  5. class Persona {
  6.  public:
  7.   Persona(const char *n) { strcpy(nombre, n); }
  8.   Persona(const Persona &p);
  9.   virtual void VerNombre() {
  10.      cout << nombre << endl;
  11.   }
  12.   virtual Persona* Clonar() { return new Persona(*this); }
  13.  protected:
  14.   char nombre[30];
  15. };
  16.  
  17. Persona::Persona(const Persona &p) {
  18.   strcpy(nombre, p.nombre);
  19.   cout << "Per: constructor copia." << endl;
  20. }
  21.  
  22. class Empleado : public Persona {
  23.  public:
  24.   Empleado(const char *n) : Persona(n) {}
  25.   Empleado(const Empleado &e);
  26.   void VerNombre() {
  27.      cout << "Emp: " << nombre << endl;
  28.   }
  29.   virtual Persona* Clonar() { return new Empleado(*this); }
  30. };
  31.  
  32. Empleado::Empleado(const Empleado &e) : Persona(e) {
  33.   cout << "Emp: constructor copia." << endl;
  34. }
  35.  
  36. class Estudiante : public Persona {
  37.  public:
  38.   Estudiante(const char *n) : Persona(n) {}
  39.   Estudiante(const Estudiante &e);
  40.   void VerNombre() {
  41.      cout << "Est: " << nombre << endl;
  42.   }
  43.   virtual Persona* Clonar() {
  44.      return new Estudiante(*this);
  45.   }
  46. };
  47.  
  48. Estudiante::Estudiante(const Estudiante &e) : Persona(e) {
  49.   cout << "Est: constructor copia." << endl;
  50. }
  51.  
  52. int main() {
  53.   Persona *Pepito = new Estudiante("Jose");
  54.   Persona *Carlos = new Empleado("Carlos");
  55.   Persona *Gente[2];
  56.  
  57.   Carlos->VerNombre();
  58.   Pepito->VerNombre();
  59.  
  60.   Gente[0] = Carlos->Clonar();
  61.   Gente[0]->VerNombre();
  62.  
  63.   Gente[1] = Pepito->Clonar();
  64.   Gente[1]->VerNombre();
  65.  
  66.   delete Pepito;
  67.   delete Carlos;
  68.   delete Gente[0];
  69.   delete Gente[1];
  70.  
  71.   return 0;
  72. }
  73.  
  74.  

La duda que tengo es la siguiente:
Si mal no tengo entendido el puntero "this" hace referencia al objeto desde cual se está llamando a una función (por ejemplo).

Entonces, al llamar a la función "clonar", tengo lo siguiente:
Código
  1. virtual Persona* Clonar() {
  2.      return new Estudiante(*this);
  3.   }
  4.  

Se supone que el parámetro "*this" hace referencia al objeto desde cuál se está llamando, que es de tipo "Persona*", pero el constructor de Estudiante, recibe un estudiante como parámetro y no una Persona. ¿Por qué es válido a hacer eso?

Sé que por polimorfismo, una persona puede ser igual a un estudiante, siempre y cuando estudiante herede de persona. Pero, ¿por qué si la función recibe un parámetro de tipo estudiante puede recibir uno de tipo persona? Es decir, estoy haciendo un estudiante igual a una persona (lo opuesto a lo que mencioné primeramente). Eso debería ser incorrecto, pero no lo es, ¿alguien me puede explicar por favor por qué?

Me estoy ahogando en un vaso de agua, lo sé. xD


« Última modificación: 11 Junio 2016, 01:39 am por Zodiak98 » En línea

AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.705


🏴 Libertad!!!!!


Ver Perfil WWW
Re: [DUDA] Polimorfismo.
« Respuesta #1 en: 11 Junio 2016, 02:56 am »

A ver.

Lo opuesto no te da error?

Código
  1. Estudiante *Pepito = new Persona("Jose");

Por que segun yo esta correcto el codigo que muestras

Segun entiendo a todos los objetos se le puede hacer cast a un objeto de una clase heredada.

Igual me puedo equivocar tengo tiempo que no trabajo con objetos xD.

Saludos


En línea

avesudra


Desconectado Desconectado

Mensajes: 724


Intentando ser mejor cada día :)


Ver Perfil
Re: [DUDA] Polimorfismo.
« Respuesta #2 en: 11 Junio 2016, 17:37 pm »

Hola, el polimorfismo es un pelín complicado, tu problema es tu noción de que cuando haces un moldeado a Persona*, el objeto ya es de tipo persona cuando esto es falso o verdadero dependiendo del método al que se llame.

Bien, cuando tu tienes tu objeto Estudiante y haces que un puntero de tipo Persona apunte a ese objeto, no quiere decir que el Estudiante ahora sea una Persona (de hecho siempre lo ha sido). Entonces al hacer:

Código
  1. Gente[0] = Carlos->clonar();

Estás llamando al método Empleado::Clonar() por ser el método virtual(si no fuese virtual llamaría a Persona::Clonar() y el *this sería de tipo Persona) y estar definido de nuevo en la clase Empleado. De hecho en el return de dicha función, es decir aquí:

Código
  1. virtual Persona* Clonar() { return new Empleado(*this); }

Se llama al constructor de copia de Empleado, y *this por supuesto no es una Persona, es un Empleado (porque el método al que se llama está en la clase empleado). Ahora el problema es que en el constructor de copia de Empleado tenemos esto:
Código
  1. Empleado::Empleado(const Empleado &e) : Persona(e) {
  2.   cout << "Emp: constructor copia." << endl;
  3. }

Pero claro primero tenemos que llamar al constructor de copia de Persona, pero le estamos pasando un Empleado, ¿por qué el compilador no nos da error aquí? Pues porque es una conversión hacia arriba en la jerarquía de clases y esta conversión implícitaes legal.

Es decir que en este pedazo de código lo que nos saldría sería:

Código:
Per: constructor copia.
Emp: constructor copia.

Si todavía no me crees puedes probar a compilar y ejecutar este código modificado y simplificado que te lo muestra (también te muestra de qué tipo es *this en cada caso):

Código
  1. #include <iostream>
  2. #include <cstring>
  3. #include <typeinfo>
  4.  
  5. /** Si a los metodos les quitas los virtual, veras que se llama a A::Clonar **/
  6.  
  7. using namespace std;
  8.  
  9. struct A
  10. {
  11.    A() {}
  12.    A(const A& a);
  13.    virtual A* Clonar()
  14.    {
  15.        cout << "A::Clonar " << typeid(*this).name() << endl;
  16.        return new A(*this);
  17.    }
  18. };
  19.  
  20. A::A(const A &a)
  21. {
  22.    cout << "A: constructor copia." << endl;
  23. }
  24.  
  25. struct B : public A
  26. {
  27.    B() : A() {}
  28.    B(const B &e);
  29.  
  30.    virtual A* Clonar()
  31.    {
  32.        cout << "B::Clonar " << typeid(*this).name() << endl;
  33.        return new B(*this);
  34.    }
  35.  
  36. };
  37.  
  38. B::B(const B& b) : A(b)
  39. {
  40.    cout << "B: constructor copia." << endl;
  41. }
  42.  
  43. int main()
  44. {
  45.    A *a = new B;
  46.  
  47.    a->Clonar();
  48.  
  49.    delete a;
  50.  
  51.    return 0;
  52. }
  53.  

« Última modificación: 11 Junio 2016, 17:48 pm por avesudra » En línea

Regístrate en
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
NekroAyuda: Polimorfismo
Programación Visual Basic
NekroByte 5 4,302 Último mensaje 11 Junio 2005, 02:38 am
por NekroByte
Polimorfismo
Ejercicios
zenydark 1 4,012 Último mensaje 8 Junio 2010, 07:13 am
por leogtz
polimorfismo
Programación C/C++
carmen_iriarte 1 2,683 Último mensaje 13 Julio 2010, 04:37 am
por nicolas_cof
POLIMORFISMO!!! (Resuelto)
Programación C/C++
¡Micronet! 3 3,303 Último mensaje 23 Octubre 2010, 01:52 am
por ¡Micronet!
Duda, reemplazo de IF por Polimorfismo.
.NET (C#, VB.NET, ASP)
n-utz 2 3,900 Último mensaje 30 Junio 2017, 03:05 am
por n-utz
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines