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

 

 


Tema destacado: Guía rápida para descarga de herramientas gratuitas de seguridad y desinfección


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema con herencia múltiple[C++][?]
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con herencia múltiple[C++][?]  (Leído 2,239 veces)
xalcoz

Desconectado Desconectado

Mensajes: 2


Ver Perfil
Problema con herencia múltiple[C++][?]
« en: 8 Enero 2017, 18:22 pm »

Tengo un fallo que no logro entender en este programa de herencia múltiple de clases abstractas. El compilador me acepta el casting sin problemas, pero a la hora de ejecutar el programa, me imprime por pantalla 2 veces la operación A en vez de primero la A y luego la B, a pesar de que la variable B no debería de tener acceso a esa función, ¿alguien sabe por qué?

Código:
#include <iostream>
using namespace std;

class A{
public:
    virtual void opA() = 0;
};

class B{
public:
    virtual void opB() = 0;
};

class AB: public A, public B{
public:
    void opA(){
        cout<<"Operacion A"<<endl;
    }
    void opB(){
        cout<<"Operacion B"<<endl;
    }
};


int main(){
    A* variableA = new AB();
    B* variableB = reinterpret_cast<B*>(variableA);

    variableA->opA();
    variableB->opB();

    delete variableA;
    return 0;
}


En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Problema con herencia múltiple[C++][?]
« Respuesta #1 en: 8 Enero 2017, 18:57 pm »

Para convertir un puntero a un objeto de una clase a otra clase, tienes 3 casts posibles:
  • static_cast: En el momento de compilar, comprueba si lo puede convertir. En tu caso, estás convirtiendo un A* a un B*. Como A* no hereda de B*, dará error. (Aunque sea un AB*, es una variable A* lo que estás convirtiendo a B*)
  • dynamic_cast: En vez de comprobar a la hora de compilar, lo hace mientras se ejecuta. Este va a comprobar si se puede hacer el cast, y si no se puede, lanzará una excepción (En este caso se puede, y no tendrás problema).
  • reinterpret_cast: Este cast no hace comprobaciones. Se limita a tratar la secuencia de bytes del objeto como si de otro objeto se tratase. En este caso, eso no es suficiente, y por eso falla.

Aquí, tu opción es dynamic_cast. Otra opción (bastante mejor a mi parecer), es utilizar un objeto AB*:
Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class A{
  5. public:
  6.    virtual void opA() = 0;
  7. };
  8.  
  9. class B{
  10. public:
  11.    virtual void opB() = 0;
  12. };
  13.  
  14. class AB: public A, public B{
  15. public:
  16.    void opA(){
  17.        cout<<"Operacion A"<<endl;
  18.    }
  19.    void opB(){
  20.        cout<<"Operacion B"<<endl;
  21.    }
  22. };
  23.  
  24.  
  25. int main(){
  26.    AB* ab = new AB();
  27.    A* variableA = ab;
  28.    B* variableB = ab;
  29.  
  30.    variableA->opA();
  31.    variableB->opB();
  32.  
  33.    delete ab;
  34.    return 0;
  35. }

No necesitarás hacer casts (el cast implícito funciona correctamente en este caso), y además tendrás la certeza de que los tipos son siempre válidos.

En tu ejemplo, estás convirtiendo un A* a un B*. Viendo el código, sabemos que eso funciona, pero no es realmente válido, pues esas clases no tienen relación.

Este último método es preferible ante el dynamic_cast porque te dará error en tiempo de compilación (preferible a una excepción), y la transformación es más rápida (dynamic_cast hace comprobaciones que podemos obviar).

Cuidado con reinterpret_cast a la hora de trabajar con clases. Mejor evitarlo, especialmente cuando se utiliza herencia múltiple.
Un caso de uso de reinterpret_cast podría ser:
Código
  1. int n = 456;
  2. char* bytesDeN = reinterpret_cast<char*>(&n);


EDITO: Y sobre el por qué hace lo que dices, pues: reinterpret_cast en ese caso no hará un cast correcto, y el comportamiento será indefinido. Probablemente, como opA es la primera función, B la coja como si fuera opB. En cualquier caso, este comportamiento es indefinido y no es relevante. Simplemente, debe evitarse.


« Última modificación: 8 Enero 2017, 19:01 pm por ivancea96 » En línea

xalcoz

Desconectado Desconectado

Mensajes: 2


Ver Perfil
Re: Problema con herencia múltiple[C++][?]
« Respuesta #2 en: 8 Enero 2017, 19:14 pm »

¡Gracias por la respuesta! Ya me estaba volviendo loco porque no entendía qué estaba pasando, me ha funcionado el código perfectamente con las dos soluciones que me has proporcionado :D
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines