Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Herencia

Estas en el tema de Herencia en el foro de C/C++ en Foros del Web. Buenas Tengo una duda relacionada con herencia que podría tener varias soluciones, y me gustaría saber vuestra opinión. Mi clase padre sería algo así: class ...
  #1 (permalink)  
Antiguo 24/09/2009, 08:44
 
Fecha de Ingreso: septiembre-2007
Mensajes: 5
Antigüedad: 16 años, 7 meses
Puntos: 0
Herencia

Buenas

Tengo una duda relacionada con herencia que podría tener varias soluciones, y me gustaría saber vuestra opinión.

Mi clase padre sería algo así:

class Padre {
Padre() {
...
funcion();
}

void funcion() {
...
}
}

La clase hija sobrecarga la función:

class Hijo : public Padre {
void funcion() {
...
}
}


Al instanciar la clase hija y ejecutarse el constructor de la clase base, me gustaría que llamara a la función sobrecargada en la hija, y sin embargo se ejecuta la función base.

Es obvio que esta no es la forma de hacerlo, pero no se me ocurre ninguna forma elegante y limpia de resolverlo.

Podría quitar la llamada a la función en el constructor padre y hacer:

Hijo* hijo = new Hijo();
hijo->funcion();

pero en realidad son muchas las funciones que utilizo dentro del constructor, y varias las clases hijas, con lo que se haría bastante farragoso.

Os agradecería cualquier ayuda al respecto.

Última edición por alais; 25/09/2009 a las 05:56
  #2 (permalink)  
Antiguo 24/09/2009, 09:03
 
Fecha de Ingreso: febrero-2004
Ubicación: Buenos Aires
Mensajes: 60
Antigüedad: 20 años, 2 meses
Puntos: 0
Respuesta: Herencia

Hola,

Creo que tenes que declar a la funcion como virtual.
En googel hay un monton de informacion.
  #3 (permalink)  
Antiguo 24/09/2009, 09:24
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Herencia

Hola,

Cita:
Iniciado por haidion Ver Mensaje
Creo que tenes que declar a la funcion como virtual.
En googel hay un monton de informacion.
No, eso no cambia nada.

Hay algo que hay que entender en el principio de herencia, es que la herencia va siempre en sentido único: el hijo conoce al padre, pero el padre no conoce al hijo (es por eso que en UML, la flecha de herencia va del hijo hasta el padre). Por ejemplo el codigo siguiente:
Código:
struct Padre //suelo usar struct en vez de class para evitar declarar todo en publico, pero es exactamente igual
{
   Padre(){f();}
   virtual void f() = 0;
};

struct Hijo : public Padre
{
   f() { std::cout << "Hijo::f() llamada" << std::endl; }
};
ni siquiera compila, porque como el padre no se nada del hijo, ni siquiera se que esta función f() existe (solo se que esta función debe existir, pero nada mas).

Este problema se puede arreglar de varias maneras. Las que conozco son:
. el patron de diseño factory (hacer una clase externa que se encarga de construir el Hijo.
. poner la función en el constructor del hijo

Seguro que hay mas maneras de hacer, pero como yo siempre uso una factory (este patrono arregla este problema y varios otros), no conozco otras.
  #4 (permalink)  
Antiguo 24/09/2009, 09:39
 
Fecha de Ingreso: febrero-2004
Ubicación: Buenos Aires
Mensajes: 60
Antigüedad: 20 años, 2 meses
Puntos: 0
Respuesta: Herencia

Una opcion que tenes es usar funciones virtuales y una función de inicializacion en la clase base.

class base{
public:
base(){}
void Init(){funcion();}
virtual void funcion();
}
  #5 (permalink)  
Antiguo 24/09/2009, 09:59
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Herencia

bueno, es una solucion, pero te obliga a usar la clase Hijo como puntero especializado de Padre, es decir asi:
Código:
Padre * hijo = new Hijo();
hijo->Init();
porque Hijo no tiene funccion Init(). (bueno, tambien hay trampas, usando un reinterpret_cast con RTTI, pero es horrible).
Eso es una debilidad del c++, y es un poco complicado. Para entenderlo bien, el mejor es entender el LSP. Y aun mejor es aplicarlo ;)
  #6 (permalink)  
Antiguo 24/09/2009, 10:51
 
Fecha de Ingreso: septiembre-2007
Mensajes: 5
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: Herencia

Vaya, no conocía el patrón de diseño Factory... la verdad es que es la primera vez que me surge este problema.

Muchas gracias por las respuestas!
  #7 (permalink)  
Antiguo 24/09/2009, 14:30
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Herencia

Pues el tema de la instanciación de los objetos es realmente crucial, y el problema es que el c++ es un poco complicado comparado con otros lenguajes. Bueno, no es que es mas complicado, sino es el aspecto multi-paradigma del c ++ ofrece varias posibilidades de manejarlo (puedes también usar templates por ejemplo), cada una teniendo especificidades de manera que una será preferible a otra según el contexto. Al final, depende de cómo vas a usar tus objetos en tu programa, y los problemas habra que resolver. Y el patrono factory resuelve algunos de estos problemas, pero no todos. Es por eso que la solución propuesta por haidion puede ser mejor, y hay mucha gente que lo usa regularmente (el clásico RAII vs función Init() ). A mi no me gusta demasiado porque no respeta el RAII ni el LSP, pero a veces puede ser perfectamente legítima.
Depende de tu contexto.
  #8 (permalink)  
Antiguo 25/09/2009, 03:42
 
Fecha de Ingreso: septiembre-2007
Mensajes: 5
Antigüedad: 16 años, 7 meses
Puntos: 0
Respuesta: Herencia

Ok, ya entendí el problema. Al estar la llamada a la función en el constructor de la clase base, es imposible que pueda llamar a la versión sobrecargada de la función, pues el objeto hijo aún no existe!

Efectivamente con un método Init() sí consigo el efecto esperado.

Gracias a ambos
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:07.