Test Foro de elhacker.net SMF 2.1

Programación => Programación C/C++ => Mensaje iniciado por: xalcoz en 8 Enero 2017, 18:22 PM

Título: Problema con herencia múltiple[C++][?]
Publicado por: xalcoz 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é?


#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;
}
Título: Re: Problema con herencia múltiple[C++][?]
Publicado por: ivancea96 en 8 Enero 2017, 18:57 PM
Para convertir un puntero a un objeto de una clase a otra clase, tienes 3 casts posibles:

Aquí, tu opción es dynamic_cast. Otra opción (bastante mejor a mi parecer), es utilizar un objeto AB*:
Código (cpp) [Seleccionar]
#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(){
   AB* ab = new AB();
   A* variableA = ab;
   B* variableB = ab;

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

   delete ab;
   return 0;
}


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 (cpp) [Seleccionar]
int n = 456;
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.
Título: Re: Problema con herencia múltiple[C++][?]
Publicado por: xalcoz 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