C/Visual C - problema con las clases heredadas y abstractas

 
Vista:

problema con las clases heredadas y abstractas

Publicado por gothmog (12 intervenciones) el 09/02/2003 01:28:14
Buenas, hasta ahora solo habia trabajado con una o dos clases, pero ahora estoy varias que heredan de una misma clase padre. El problema que tengo es que al incluir una clase hija, se declara automaticamente la clase padre, por lo que si incluyo otra clase hija, me da error de que se ha declarado dos veces la clase padre. No se si me explico.

Yo tengo

class Padre{
// ...
public:
virtual m1() = 0{}
}

class Hija1:public Padre{
// ...
public:
m1(){ // codigo}
}

class Hija2:public Padre{
// ...
m1(){ // codigo}
}

Esto en tres archivos distintos .h

Cuando en el .cpp principal pongo:

#include <Hija1.h> // Aqui ya me incluye a Padre.h Por tanto si pongo:

#include <Hija2.h> // Me da error

Sin embargo necesito usar ambas clases.

Tb me he dado cuenta que si en la clase Padre por ejemplo pongo '#include <iostream.h>' y luego la uso en el .cpp principal, no me hace falta volver a incluir el iostream. Sin embargo, si pongo el incluir no me da error. Cosa que si me hace con mis propias clases. Que hago para evitar ese error de duplicacion?

Me parece que todo ronda hacia el mismo tema, pero no lo veo muy claro, a ver si alguien pudiera echarme una mano.

P.D.: Aunque no me he parado a pensarlo demasiado, supongo que esto tendria facil solucion usando polimorfismo. El problema es que se supone que todavia no se polimorfismo, de modo que tengo que obviar su existencia.

Gracias por las respuestas.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:problema con las clases heredadas y abstractas

Publicado por Edsger (1 intervención) el 09/02/2003 06:12:40
en cada .H agrega lo siguiente

#ifndef __NOMBRECLASE
#define __NOMBRECLASE
... Resto del .h ...
#endif

Esto pregunta si la etiquieta no está definida antes de cargar la definición, es un if a nivel del compilador
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Una cosa mas

Publicado por gothmog (1 intervención) el 09/02/2003 16:05:41
Lo primero, gracias por la respuesta.

Tengo otra duda sobre las clases heredadas. Es lo siguiente.

Yo tengo la clase Padre, en la cual defino el constructor

class Padre{
// ...
public:
Padre(int a, int b);
//..
};

Y una clase hija con otro constructor propio:

class Hija:public Padre{
// ...
public:
Hija (int a, int b, int c);
// ...
};

Yo lo que quiero es, cuando se llame al constructor de la clase Hija, pasar los parametros a y b al constructor de la clase Padre. Algo asi:

Hija::Hija(int a, int b, int c){
Padre(a,b); // Tambien he probado: Padre::Padre(a,b);
C = c;
}

Pero, aunque no me da error al compilar, si que observo que no funciona. Mientras depuro veo que se ejecuta todo bien pero luego no tiene efecto en los atributos de la clase Hija. Donde estoy metiendo la pata?

Lo que si que ocurre es que si el constructor de la clase Padre e Hija fueran:

Padre::Padre(){
A = 1;
B = 1;
}

Hija::Hija(){
C = 1;
}

Al llamar al constructor de Hija, se llama inmediatamente al de Padre. Pero pq no puedo usar los constructores parametrizados?

Gracias por la ayuda.

P.D.: En CBuilder 5
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Una cosa mas

Publicado por Googol (255 intervenciones) el 09/02/2003 23:40:43
Para llamar al constructor de la padre en la hija tienes que hacer:

Hija::Hija(int a, int b, int c) : Padre(a, b) {
C = c;
}

Es decir, poniendo después del prototipo, el ":" y el constructor de la padre al que quieres llamar.
Lo que tú estás haciendo funciona, porque la llamada al constructor de la clase Padre crea un nuevo objeto, que no es guardado por nadie (en ninguna variable), y se destruirá posteriormente. Por eso al depurar ves que el constructor de la padre se ejecuta, pero en realidad se ejecuta con un "this" diferente al usado en el constructor de la clase hija.

Suerte!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Una cosa mas

Publicado por gothmog (12 intervenciones) el 10/02/2003 00:34:36
ok, muchas gracias!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Una ultima duda (casting)

Publicado por gothmog (3 intervenciones) el 10/02/2003 02:26:37
Bueno, prometo no molestar ya mas en los proximos dias :)

Vamos a ver, yo tengo estas clases y este main:

class Padre{
int a1, a2;
public:
virtual void m1(){ cout << "Metodo Padre\n"; }
};

class Hija:public Padre{
int a3;
public:
void m1(){ cout << "Metodo 1 Hija\n"; }
void m2(){ cout << "Metodo 2 Hija\n"; }
};

int main{
Padre * punt;

punt = new Hija1;
punt->m2();
delete(punt);
}

Pues esto me da error de compilacion, ya que me dice que m2 no es un miembro de Padre. Se que esto se soluciona haciendo un casting (por lo menos en Java es asi), de modo que el compilador tome a punt como un puntero del tipo Hija2, pero no se como es la sintaxis. He probado varias cosas pero nada. Que hago para que trague y me deje compilar?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Una ultima duda (casting)

Publicado por Googol (255 intervenciones) el 10/02/2003 15:20:43
¡Hola!

Bueno... no es muy "limpio" hacer una conversión de tipos ahí, pero vamos :-)
El problema que estás teniendo es seguramente por la precedencia de los operadores.
Lo primero que se te ocurrirá será:

(Hija*) punt->m2();

El problema es que el operador de llamada al método tiene más precedencia que la conversión, por lo que lo que estás haciendo es en realidad intentando convertir _el resultado_ de la función o método al que llamas.
La solución es usar paréntesis:

((Hija*)punt)->m2();

Suerte!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Una ultima duda (casting)

Publicado por gothmog (3 intervenciones) el 10/02/2003 19:21:38
Muy cierto! Vaya, muchas gracias por la ayuda.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:problema con las clases heredadas y abstractas

Publicado por Germán (2 intervenciones) el 10/02/2003 21:25:12
Creo que lo que te pasa a ti también me ha pasado a mí alguna vez. El iostream no te da error porque si lo incluyes dos veces, tiene una rutina para detectarlo y no se duplica. Te explico cómo evitar que dupliques código por incluir la clase padre en varios ficheros. En el fichero de la clase padre (y te recomiendo que lo hagas en todos los ficheros de clases a partir de ahora) pon lo siguiente:

#ifndef CLASE_PADRE
#define CLASE_PADRE

//Código de la clase

#endif

Te explico: el #ifndef sirve para lo siguiente: Tú al incluir cada una de las clases hija, incluyes de nuevo la clase padre. Pero si usas el #ifndef NOMBRE_VARIABLE y el define, el compilador define una variable simbólica con ese nombre. Si vuelve a detectar que quieres incluir otra vez ese fichero, no lo incluirá de nuevo porque NOMBRE_VARIABLE ya está definido, y por lo tanto, no lo vuelve a incluir. Sé que me explico un poco mal, pero bueno, tú pon lo que he dicho arriba y tiene que funcionarte. Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:problema con las clases heredadas y abstractas

Publicado por gothmog (3 intervenciones) el 11/02/2003 11:21:10
Gracias por la aclaracion.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar