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

 

 


Tema destacado: AIO elhacker.NET 2021 Compilación herramientas análisis y desinfección malware


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

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Constructores de conversión y casteos.
« en: 22 Julio 2013, 16:56 pm »

Hola a todos, intentaré ser lo mas conciso posible.

He leído y comprobado que en java no se puede hacer un cast de una superclase a una subclase, así que me propuse intentarlo en C++:

Al intentarlo observo que con static_cast, reinterpret_cast y al estilo C, compila y ejecuta, pero efectivamente los nuevos atributos de la clase derivada no son inicializados (yo pensaba que con estos castings se haría llamada al constructor apropiado, pero no es así). Obviamente, no funciona como debería.

¿Como puedo hacer para poder castear la superclase a una subclase con dynamic_cast y que todo se inicialice bien?

PD.
No se si se podrá pero, ¿sobrecargando dynamic_cast de alguna manera?

He intentado sobrecargar el operador '=' para que al hacer la asignación todo funcione bien. El problema ha sido que lo he hecho con referencias, para conseguir lo que quiero ¿tienen que ser punteros a la fuerza porque necesito polimorfismo?:
(El operador '=' hará cosas distintas si hago 'SuperClase=SuperClase' que si hago 'SuperClase=SubClase')




En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Constructores de conversión y casteos.
« Respuesta #1 en: 22 Julio 2013, 17:02 pm »

Para poder hacer un cast a una subclase y que el cast sea correcto, la instancia afectada tiene que ser, necesariamente, de la subclase.

Me explico:

Código
  1. Class A
  2. { };
  3.  
  4. Class B : public A
  5. { };
  6.  
  7. int main ( ... )
  8. {
  9.  A* puntero1 = new A( );
  10.  A* puntero2 = new B( );
  11.  
  12.  // este caso retornará 0 porque puntero1 no es de la subclase B
  13.  B* clase_b1 = dynamic_cast< B* >( puntero1 );
  14.  
  15.  // este caso retornará un puntero válido
  16.  B* clase_b2 = dynamic_cast< B* >( puntero2 );
  17. }

Luego, dado que para que el cast funcione correctamente, la instancia original ha de ser de la subclase ( o de una subclase de la subclase ), necesariamente has tenido que crear una instancia de la subclase y, al hacer esa creación, se han tenido que inicializar necesariamente todos los miembros de la clase.

Si esto no es así es porque se te ha olvidado inicializar algo en el constructor.


En línea

SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Constructores de conversión y casteos.
« Respuesta #2 en: 22 Julio 2013, 19:40 pm »

Gracias por la respuesta.

Luego es imposible tener una superclase A, una clase derivada B, construir un objeto como clase A, y castearlo a clase B, es decir:

Código:
class A{};
class B: extends A{};

int main(){
   A *a=new A();

   B *b=dynamic_cast<B *>(a);
  //Esto da error.

  B *b2=static_cast<B *>(a);
//Esto no da error, el problema es que los atributos que incorpora 'B' no son    
//inicializados, a no ser que lo estubiesen ya.

//Tampoco hay manera de llamar a un constructor automaticamente al hacer ese
//static_cast para que las variables que incorpora 'B' sean inicializadas, ¿cierto?  

}        

Muchas Gracias

« Última modificación: 22 Julio 2013, 21:19 pm por SARGE553413 » En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Constructores de conversión y casteos.
« Respuesta #3 en: 22 Julio 2013, 22:18 pm »

dynamic_cast hace chequeos que verifican que, efectivamente, se puede hacer el cast a la clase destino. Esto solo es posible cuando la instancia apuntada es de la clase destino o de alguna clase hija... en caso contrario, el cast retornará un puntero nulo.

static_cast símplemente comprueba que el cast (a pelo) es válido. Es un chequeo muucho más sencillo que el dinámico y, por ello, más propenso a errores... por ejemplo que te deje hacer lo que estabas comentando.

Está claro que si tu tienes una superclase A... creas una instancia de esta clase y luego intentas hacer un cast a su subclase B... los miembros de esta subclase no pueden estar bien. En primer lugar porque en c++, a diferencia de en java, los miembros no se inicializan por defecto.

El constructor de A sólo sabe inicializar la parte que es propia de A... pero no sabe nada de la parte de B... luego esa parte siempre va a quedar con valores aleatorios.

Tu piensa que en el fondo, una clase no deja de ser x bytes en memoria y una serie de funciones que hacen uso de posiciones específicas de esa memoria... el concepto de clase solo tiene sentido para tí... la máquina no entiende de eso.
En línea

SARGE553413

Desconectado Desconectado

Mensajes: 176


Ver Perfil
Re: Constructores de conversión y casteos.
« Respuesta #4 en: 24 Julio 2013, 14:25 pm »

Gracias de nuevo por la respuesta.
Eso mismo me planteba yo ( la vision de la clase en memoria) por eso preguntaba si si habia alguna manera de llamar al constructor de la clase B durante el casteo para construirla bien pero veo que no,ok.

Sin embargo ahora mi pregunta es que pasa si la superclase es abstracta. Supongamos que tengo una superclase A y dos que heredan  C y D. Si defino un metodo que devuelve un puntero a A, si que puedo castear una superclase a una de sus clases derivadas sin problema. Esto es porq dentro del metodo he construido el objeto como una de laa clases derivadas ( necesariamente porque  esabstracta) ¿correcto?


Y si dentro deo metodo conatruyo la clase como B y tras delver el puntero mo casteo a C?
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Constructores de conversión y casteos.
« Respuesta #5 en: 24 Julio 2013, 15:03 pm »

Eso mismo me planteba yo ( la vision de la clase en memoria) por eso preguntaba si si habia alguna manera de llamar al constructor de la clase B durante el casteo para construirla bien pero veo que no,ok.

Efectivamente no se puede. Los constructores son llamados únicamente al crear la clase... una vez que ya está creada los constructores no son invocados de nuevo. Además, tu piensa que las subclases, como norma general, necesitan más memoria que las superclases... y la memoria ha de ser secuencial. Una vez ya has hecho una reserva de memoria no puedes garantizar que una nueva reserva se realice inmediatamente después... luego no podrías crear correctamente la nueva clase.

Sin embargo ahora mi pregunta es que pasa si la superclase es abstracta. Supongamos que tengo una superclase A y dos que heredan  C y D. Si defino un metodo que devuelve un puntero a A, si que puedo castear una superclase a una de sus clases derivadas sin problema. Esto es porq dentro del metodo he construido el objeto como una de laa clases derivadas ( necesariamente porque  esabstracta) ¿correcto?

A ver, voy a intentar explicarlo con algo físico... para que sea más gráfico.

Tu imagínate que tienes la superclase Animal... y de ella heredan las clases Gato y Perro.

Si tu ( imagínate que eres una especie de dios ), creas un Gato... a ese gato lo puedes identificar como gato o como animal... pero nunca llegará a ser un perro ( tus poderes no dan para tanto ).

Si en vez de un gato creas un perro pasará exactamente lo mismo, el perro podrá ser tratado como un perro o como un animal, pero nunca como un gato.

El polimorfismo lo que te permite es tener punteros genéricos ( de tipo superclase ), que en realidad representen a entidades heredadas... pero este mecanismo no permite experimentos de mutación genética que permitan convertir un perro en un gato.

Si tu intentas llevar a cabo esta aberración de la naturaleza te pasará lo siguiente:

Código
  1. class Animal
  2. {
  3. };
  4.  
  5. class Perro: public Animal
  6. {
  7. };
  8.  
  9. class Gato : public Animal
  10. {
  11. };
  12.  
  13. void main( )
  14. {
  15.  Animal* gato = new Gato( );
  16.  Animal* perro = new Perro( );
  17.  
  18.  Gato* gato1 = dynamic_cast< Gato* >( gato ); // ok
  19.  Gato* gato2 = static_cast< Gato* >( gato ); // ok pero menos seguro
  20.  
  21.  Perro* perro1 = dynamic_cast< Perro* >( perro ); // ok
  22.  Perro* perro2 = static_cast< Perro* >( perro ); // ok pero menos seguro
  23.  
  24.  Gato* aberracion1 = dynamic_cast< Gato* >( perro ); // devuelve 0.
  25.  Gato* aberracion2 = static_cast< Gato* >( perro ); // funciona pero la aplicación va a dar resultados incorrectos o casques.
  26.  
  27.  Perro* aberracion3 = dynamic_cast< Perro* >( gato); // devuelve 0.
  28.  Perro* aberracion4 = static_cast< Perro* >( gato); // te funciona pero la aplicación va a dar resultados incorrectos o casques.
  29. }
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Constructores en vb.net???
.NET (C#, VB.NET, ASP)
Skeletron 3 10,708 Último mensaje 14 Octubre 2009, 03:55 am
por seba123neo
constructores en java
Java
sauce19 7 5,486 Último mensaje 5 Septiembre 2011, 00:26 am
por [Case]
Constructores en Java
Java
Viky30 5 6,245 Último mensaje 27 Noviembre 2011, 18:27 pm
por satu
lio con constructores y destructores
Programación C/C++
Javincy 2 2,414 Último mensaje 8 Febrero 2012, 16:18 pm
por Javincy
Conversiones/casteos y coerciones de tipos en javascript por StringManolo
Desarrollo Web
@XSStringManolo 2 2,323 Último mensaje 1 Mayo 2020, 05:07 am
por @XSStringManolo
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines