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

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


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


Desconectado Desconectado

Mensajes: 319


Ver Perfil
Ayuda libro de polimorfismo . Solucionado
« en: 3 Marzo 2014, 17:16 pm »

Hola primero que nada alguno de ustedes sabe de algun libro de C++ que solo hable de polimorfismo y tenga algunos ejemplos un poco mas detallados.

He visto el de obsoluted C++ pero los ejemplos son un poco simples y busco algo que me haga entender a profundidad este tema.

Gracias y saludos a todos.


« Última modificación: 6 Marzo 2014, 05:47 am por nolasco281 » En línea

Lo que se puede imaginar... se puede programar.
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Ayuda libro de polimorfismo .
« Respuesta #1 en: 3 Marzo 2014, 17:44 pm »

El polimorfismo es un concepto de lo más sencillo... bien es cierto que yo en la universidad veía a gente temblando solo de pensar en ello... pero yo creo que es más por el nombre que por otra cosa.

Tú tienes una jerarquía de clases, por ejemplo

Código:
     A
     |
  -------
 |       |
 B       C

Donde A es la clase padre y B y C las hijas.

Si tú creas una clase B o una clase C ( es indiferente ) puedes gestionarlas como si fuesen directamente del tipo A:

Código
  1. std::vector< A* > lista;
  2. lista.push_back( new B( ) );
  3. lista.push_back( new C( ) );

Los cast a los padres son automáticos, no hace falta hacer un dynamic_cast... sin embargo moverte hacia abajo en la herencia sí requiere un dynamic_cast por motivos obvios... C es de tipo A, pero no es de tipo B:

Código
  1. A* clase = new C( );
  2. C* c = dynamic_cast< C* >( clase ); // puntero valido
  3. B* b = dynamic_cast< B* >( clase ); // puntero nulo, no es posible el cast

También es lógico pensar que si haces un cast al padre, los métodos propios de las clases hijas no son accesibles... no hasta que vuelvas a hacer un cast a la clase hija:

Código
  1. class A
  2. {
  3.  public:
  4.    void func1( );
  5. };
  6.  
  7. class B : public A
  8. {
  9.  public:
  10.    void func2( );
  11. };
  12.  
  13. void main( )
  14. {
  15.  A* puntero = new B( );
  16.  puntero->func1( ); // ok
  17.  puntero->func2( ); // error, A no tiene un miembro func2
  18.  
  19.  B* puntero2 = dynamic_cast< B* >( puntero );
  20.  puntero2->func1( ); // ok
  21.  puntero2->func2( ); // ok
  22. }

La excepción a esta última norma son los métodos virtuales. Si tu sobrecargas un método virtual de una clase padre, se llamará al método de la clase hija SIEMPRE.

Código
  1. class A
  2. {
  3.  public:
  4.    virtual void func1( )
  5.    { std::cout << "A" << std::endl; }
  6. };
  7.  
  8. class B : public A
  9. {
  10.  public:
  11.    void func1( )
  12.    { std::cout << "B" << std::endl; }
  13. };
  14.  
  15. void main( )
  16. {
  17.  A* ptr1 = new A( );
  18.  A* ptr2 = new B( );
  19.  
  20.  ptr1->func1( );
  21.  ptr2->func1( );
  22. }

La salida del programa será:

Código:
A
B

Un aspecto importante del polimorfismo es que al moverse en la jerarquía los punteros no tienen por qué coincidir... esto se hace muy patente con herencia múltiple:

Código
  1. class A
  2. {
  3.  int dummy;
  4. };
  5.  
  6. class B
  7. {
  8.  int dummy;
  9. };
  10.  
  11. class C : public A, public B
  12. {
  13.  int dummy;
  14. };
  15.  
  16. void main( )
  17. {
  18.  C* puntero1 = new C( );
  19.  B* puntero2 = puntero1;
  20.  A* puntero3 = puntero1;
  21.  
  22.  std::cout << "Puntero clase C: " << static_cast< void* >( puntero1 ) << std::endl;
  23.  std::cout << "Puntero clase B: " << static_cast< void* >( puntero2 ) << std::endl;
  24.  std::cout << "Puntero clase A: " << static_cast< void* >( puntero3 ) << std::endl;
  25. }

Este comportamiento es debido a que C++ introduce unos identificadores en las clases para poder navegar por la jerarquía ( estos identificadores son los que usa dynamic_cast para saber si un cast es válido o no )

Y poco más que contar... ah sí, se me olvidaba... si en vez de puntero trabajas con la pila has de tener en cuenta que si haces un cast al padre vas a perder la herencia, ya que estarás llamando al constructor copia...

Código
  1. class A
  2. {
  3.  public:
  4.    virtual void func1( )
  5.    { std::cout << "A" << std::endl; }
  6. };
  7.  
  8. class B : public A
  9. {
  10.  public:
  11.    void func1( )
  12.    { std::cout << "B" << std::endl; }
  13. };
  14.  
  15. void main( )
  16. {
  17.  A clase1 = B( );
  18.  B clase2 = B( );
  19.  
  20.  clase1.func1( );
  21.  clase2.func1( );
  22. }

Salida:

Código:
A
B

Y esto es el polimorfismo... la gracia de esto es que es extensible... yo he puesto ejemplos con 3 clases... pero en el programa en el que trabajo el polimorfismo abarca unas 300 clases repartidas por una decena de niveles de jerarquía con herencias múltiples y demás guarrerías XD


« Última modificación: 3 Marzo 2014, 17:46 pm por eferion » En línea

nolasco281


Desconectado Desconectado

Mensajes: 319


Ver Perfil
Re: Ayuda libro de polimorfismo .
« Respuesta #2 en: 3 Marzo 2014, 18:16 pm »

Hola gracias por responder.

Una pregunta tengo una clase abstracta A y uso funciones virtuales puras, en B y C solo debería de llamar esas funciones y asignarles el código que se necesite no?

Cual es la diferencia de funciones virtuales y vistuales puras?

Como el ejemplo que pones.
Noto que en la clase A describes los métodos virtuales a usar, y en la clase B, que seria la hija, llama a la función virtual solo que con las funcionalidad que necesito (o código que deseo poner, por si no me explico).

Creo que entendí. Pero si estoy mal en algo agradecería la corrección

Gracias de nuevo.


Código
  1.    class A
  2.    {
  3.     public:
  4.       virtual void func1( )
  5.       { std::cout << "A" << std::endl; }
  6.    };
  7.  
  8.    class B : public A
  9.    {
  10.     public:
  11.       void func1( )
  12.       { std::cout << "B" << std::endl; }
  13.    };
  14.  
  15.    void main( )
  16.    {
  17.     A* ptr1 = new A( );
  18.     A* ptr2 = new B( );
  19.  
  20.     ptr1->func1( );
  21.     ptr2->func1( );
  22.    }
  23.  

Termino de hacer algunos ejemplos y te comento como me fue.
En línea

Lo que se puede imaginar... se puede programar.
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Ayuda libro de polimorfismo .
« Respuesta #3 en: 4 Marzo 2014, 09:12 am »

Cual es la diferencia de funciones virtuales y vistuales puras?

Las funciones virtuales son funciones que pueden ser sobreescritas en las clases hijas. Las funciones virtuales puras son funciones virtuales que no tienen código en la clase padre.

Cuando tú en una clase defines una función virtual pura la clase pasa a ser abstracta, es decir, no puedes crear instancias de esta clase.

Código
  1.  
  2. class A
  3. {
  4.  public:
  5.    virtual void func( ) = 0;
  6. };
  7.  
  8. class B : public A
  9. {
  10.  public:
  11.    void func( )
  12.    { std::cout << "B" << std::endl; }
  13. };
  14.  
  15. class C : public A
  16. {
  17.  public:
  18.    void otro( )
  19.    { std::cout << "C" << std::endl; }
  20. };
  21. void main( )
  22. {
  23.  A* var1 = new A( ); // Error, A es abstracta
  24.  A* var2 = new B( ); // Correcto
  25.  A* var3 = new C( ); // Error C es abstracta porque no implementa 'func'
  26. }

Como el ejemplo que pones.
Noto que en la clase A describes los métodos virtuales a usar, y en la clase B, que seria la hija, llama a la función virtual solo que con las funcionalidad que necesito (o código que deseo poner, por si no me explico).

Los métodos virtuales permiten que las clases hijas implementen un código propio sobre una función declarada en el padre, de tal forma que ese código sea llamado siempre independientemente de cual sea "la forma" mediante la cual se acceda a dicho método:

Código
  1. class A
  2.    {
  3.     public:
  4.       void func1( )
  5.       { std::cout << "A" << std::endl; }
  6.    };
  7.  
  8.    class B : public A
  9.    {
  10.     public:
  11.       void func1( )
  12.       { std::cout << "B" << std::endl; }
  13.    };
  14.  
  15.    void main( )
  16.    {
  17.     A* ptr1 = new A( );
  18.     A* ptr2 = new B( );
  19.     B* ptr3 = dynamic_cast< B*>( ptr2 );
  20.  
  21.     ptr1->func1( );
  22.     ptr2->func1( );
  23.     ptr3->func1( );
  24.    }

Fíjate que he quitado el modificador de "virtual" en la clase padre. En este caso la salida del programa será:

Código:
A
A
B

Esto es así porque, al no ser virtual, el resultado de func1( ) dependerá del tipo de puntero ( A o B ) y no del tipo de la instancia a la que apunta ( A o B ).

Como corolario, en C++11 se añaden dos modificadores adicionales para estos casos; uno de ellos es especialmente útil. Se trata del modificador "override".

"override" se usa en las funciones virtuales que sobreescribes en las clases hijas y su función es obligar al compilador a que se asegure de que realmente la función esta sobreescribiendo una función virtual... si no es así resulta un error de compilación.

Código
  1. class A
  2. {
  3.  public:
  4.    virtual void func( )
  5.    { }
  6.  
  7.    virtual void funcConNombreRarillo( )
  8.    { }
  9. };
  10.  
  11. class B : public A
  12. {
  13.  public:
  14.    // ok
  15.    voif func( ) override;
  16.  
  17.    // Error: no hay ninguna func( int ) declarada virtual en el padre
  18.    void func( int param ) override;
  19.  
  20.    // Error: Se me ha colado una l de mas en el nombre
  21.    void funcConNombreRarilllo( ) override;
  22. };

El modificador "override" es bastante útil porque, de otra forma" no tenemos posibilidad de detectar estos errores a la hora de programar. Es muy sencillo equivocarse en la firma de la función y es ciertamente complicado detectar el problema.

En línea

nolasco281


Desconectado Desconectado

Mensajes: 319


Ver Perfil
Re: Ayuda libro de polimorfismo .
« Respuesta #4 en: 6 Marzo 2014, 05:46 am »

Muchas gracias eferion siempre sancando la dudas de ensima.

lamento responder tan tarde no tenia internet. saludos.
En línea

Lo que se puede imaginar... se puede programar.
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Ayuda libro de polimorfismo . Solucionado
« Respuesta #5 en: 6 Marzo 2014, 08:34 am »

Sin problemas.

Tu pregunta que seguro que alguien sabe la respuesta ;)
En línea

dato000


Desconectado Desconectado

Mensajes: 3.034



Ver Perfil
Re: Ayuda libro de polimorfismo . Solucionado
« Respuesta #6 en: 6 Marzo 2014, 16:55 pm »

Vaya genial explicación, habia visto esa parte para c#, pero no para c++, virtuales yeah!!!!!!!

dejo una pequeña modificación del código porque no corria correctamente, solo detalles.


Código
  1. #include "iostream"
  2. using namespace std;
  3.  
  4. class A
  5. {
  6.    public:
  7.        virtual void func() {}; // se supone que es abstracta
  8. };
  9.  
  10. class B : public A
  11. {
  12.    public:
  13.            void func()
  14.            {
  15.                cout << "Resultado B" << endl;
  16.            }
  17. };
  18.  
  19. class C : public A
  20. {
  21.    public:
  22.        void otro()
  23.        {
  24.            cout << "Resultado C" << endl;
  25.        }
  26. } ;
  27.  
  28. int main()
  29. {
  30.    //A* var1 = new A(); // No puede instanciar directamente una clase virtual
  31.    A* var2 = new B(); // Correcto, usa la instancia de clase A
  32.    //A* var3 = new C(); // clase C no usa instancia de A
  33.  
  34.    var2 -> func();
  35.  
  36.    return 0;
  37. }
  38.  

« Última modificación: 6 Marzo 2014, 18:05 pm por dato000 » En línea


eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Ayuda libro de polimorfismo . Solucionado
« Respuesta #7 en: 6 Marzo 2014, 17:02 pm »

dejo una pequeña modificación del código porque no corria correctamente, solo detalles.
Esa era justamente la idea... no corre porque al ser virtual pura no puedes instanciar clases de ese tipo.

Lo que has conseguido con ese cambio es que 'A' no sea abstracta y, por tanto, puede ser instanciable.

Vaya genial explicación, habia visto esa parte para c#, pero no para c++, virtuales yeah!!!!!!!

Celebro que te haya gustado.

Para más dudas aquí estamos :)

En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Ayuda Polimorfismo. Interfaz grafica « 1 2 »
Java
zenydark 16 8,615 Último mensaje 3 Junio 2010, 02:42 am
por zenydark
Libro de Pnl (descarga)SOLUCIONADO
Foro Libre
Senior++ 0 2,153 Último mensaje 27 Noviembre 2011, 12:26 pm
por Senior++
ayuda con programa con herencia y polimorfismo
Programación General
AGEDEAD 1 1,735 Último mensaje 30 Abril 2014, 20:15 pm
por El Benjo
Ayuda práctica polimorfismo
Programación C/C++
Fastolfe 1 1,785 Último mensaje 23 Mayo 2014, 08:18 am
por Eternal Idol
Polimorfismo c++ , restricciones del lenguaje- Ayuda Diseño
Programación C/C++
Leanic 0 1,726 Último mensaje 3 Noviembre 2016, 06:56 am
por Leanic
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines