SoloCodigo

Programación General => C/C++ => Mensaje iniciado por: Mararía en Jueves 1 de Noviembre de 2007, 21:06

Título: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Jueves 1 de Noviembre de 2007, 21:06
Hola, de nuevo por aquí... Explico mi problemilla... Tenemos que implementar la simulación de un ecosistema basándonos en las clases que hicimos para el juego de la vida (una clase tablero y una clase célula). El problema viene porque en lugar de una sola clase célula, tenemos que usar dos, derivadas ambas de la clase célula que ya hemos implementado... el caso es que, si las reglas de supervivencia, nacimiento y muerte sólo tuvieran en cuenta los objetos del mismo tipo que rodean a otro objeto, no sería tan difícil; Pero tengo que contar tanto los de un tipo como los del otro y llevar la cuenta por separado o sumar, depende... Lo único que se me ocurre es poner una variable pública ident que sea una letra en cada una de estas clases derivadas, e implementar un metodo (llamado mismaespecie, por ej) que devuelva un booleano. Hay alguna otra forma de hacerlo? Y si no la hay, el método mismaespecie debería ir en cada una de las clases derivadas o valdría en la clase base? Gracias.
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Viernes 2 de Noviembre de 2007, 21:17
Bueno.... al final, puse un identificador a la clase célula y ese identificador cambia según la célula sea de una especie u otra... ahora el problema me viene con el uso de los punteros... La clase tablero debería tener un array bidimensional de punteros a células. Creo que dicho array no está del todo bien definido (ver tablero.h)

Por otra parte, el compilador está chillando y, aunque algunos errores los he resuelto, estos son los que me quedan:
Código: Text
  1. Celula.C: In member function ‘void Celula::Actualizarestado(Celula* (*)[22], int, int)’:
  2. Celula.C:35: error: solicitud por el miembro ‘vidant’ en ‘(*(((Celula* (*)[22])(((unsigned int)i) * 88u)) + Casilla))[j]’, el cual es del tipo ‘Celula*’ que no es clase
  3. Procariota.C: In member function ‘void Procariota::Actualizarestado(Celula* (*)[22], int, int)’:
  4. Procariota.C:20: error: solicitud por el miembro ‘vidant’ en ‘(*(((Celula* (*)[22])(((unsigned int)i) * 88u)) + Casilla))[j]’, el cual es del tipo ‘Celula*’ que no es clase
  5. Eucariota.C: In member function ‘void Eucariota::Actualizarestado(Celula* (*)[22], int, int)’:
  6. Eucariota.C:21: error: solicitud por el miembro ‘vidant’ en ‘(*(((Celula* (*)[22])(((unsigned int)i) * 88u)) + Casilla))[j]’, el cual es del tipo ‘Celula*’ que no es clase
  7.  

Adjunto el código en un zip. A ver si entre todos conseguís que el cacao mental este que tengo, deje de ser tan oscuro  :P
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Domingo 4 de Noviembre de 2007, 15:34
Hola de nuevo! La mayoría de los problemas parecen haber sido solucionados... pero ahora me da un error al compilar y no lo veo!
Me dice.
Citar
Tablero.C: In constructor ‘Tablero::Tablero(int, int)’:
Tablero.C:12: error: expected primary-expression before ‘;’ token

Este es el constructor mencionado:
Código: Text
  1. Tablero::Tablero (int i, int j){ //Constructor de la clase Tablero.
  2.   limi = i+2;
  3.   limj = j+2;
  4.   casilla = new Celula *[limi];
  5.   for (int k = 0; k < limi; k++){
  6.     casilla[k] = new Celula [limj];
  7.     for (int l = 0; l < limj; l++)
  8.       casilla[k][l] = Celula; //<- Esta es la linea donde me pide una expresión primaria antes del&#59;
  9.   }
  10. }
  11.  
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Eternal Idol en Domingo 4 de Noviembre de 2007, 15:55
Código: Text
  1.  
  2. casilla[k][l] = Celula; //<- Esta es la linea donde me pide una expresión primaria antes del;
  3.  
  4.  

¿Que intentas hacer con eso? ¿Celula no es una clase acaso?
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Domingo 4 de Noviembre de 2007, 16:15
Intento meter un objeto de tipo   célula en la casilla i,j...    :(
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Eternal Idol en Domingo 4 de Noviembre de 2007, 16:19
Cita de: "Mararía"
Intento meter un objeto de tipo   célula en la casilla i,j...    :(
¿Entonces no sera new Celula en lugar de Celula?
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Domingo 4 de Noviembre de 2007, 20:39
Nop... si pongo new Celula me salta esto:

Citar
Tablero.C:13: error: no match para ‘operator=’ en ‘*((*(((Tablero*)this)->Tablero::casilla + ((Celula**)(((unsigned int)k) * 4u)))) + ((Celula*)(((unsigned int)l) * 3u))) = (((Celula*)operator new(3u)), (<anonymous>->Celula::Celula(), <anonymous>))’
Celula.h:6: nota: los candidatos son: Celula& Celula::operator=(const Celula&)

Sin embargo, si el constructor lo pongo así:
Código: Text
  1. Tablero::Tablero (int i, int j){ //Constructor de la clase Tablero.
  2.   limi = i+2;
  3.   limj = j+2;
  4.   casilla = new Celula *[limi];
  5.   for (int k = 0; k &#60; limi; k++){
  6.     casilla[k] = new Celula [limj];
  7.     for (int l = 0; l &#60; limj; l++){
  8.       Celula a;
  9.       casilla[k][l] = a;
  10.     }
  11.   }
  12. }
  13.  
al menos el compilador no chilla...
Ahora tengo dos problemillas...
El primero, el destructor, al terminar el programa, da un error de memoria. Está implementado así:
Código: Text
  1. Tablero::~Tablero (){//Destructor.
  2.   for (int i = 0; i &#60; limi; i++){
  3.     for (int j = 0; j &#60; limj; j++)
  4.       delete[] casilla[j];
  5.     delete []casilla[i];
  6.   }
  7. }
  8.  
  9.  
El segundo, no sé cómo hacer para sustituir una célula genérica en una casilla determinada por una de una especie...

Le tenia algo tal que:
Código: Text
  1. void Tablero::IntroducirCelula (int posi, int posj, Celula a){  
  2.   casilla [posi][posj] = a;
  3. }
  4.  

Pasándole una eucariota o procariota... pero que si quieres arroz, catalina! No funciona.

He porbado a poner (Eucariota a) en lugar de (Celula a)... pero tampoco.. supongo que tengo que hacer algún delete y algún new, pero como habrán comprobado, en punteros estoy NULL  :D
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Eternal Idol en Domingo 4 de Noviembre de 2007, 20:57
Depuralo, asi vas a comprender que es lo que sucede paso a paso y tal vez te ayude a entender mas el tema de punteros. Sino busca informacion al respecto en la red.
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Karman en Lunes 5 de Noviembre de 2007, 13:16
Citar
casilla[k][l] = Celula; //<- Esta es la linea donde me pide una expresión primaria antes del;

qué quieres hacer con esto? para que asignas a un array de objetos la clase? ya tienes el objeto creado, prueba hacer un:

casilla[j]->algo();

Citar
for (int i = 0; i < limi; i++){
   for (int j = 0; j < limj; j++)
     delete[] casilla[j];
   delete []casilla;
 }

S2
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Martes 6 de Noviembre de 2007, 01:17
De nuevo por aquí.. esto me está dando más problemas...

Veamos... AL final simplifiqué bastante el constructor y el destructor... Declarando el atributo privado de tablero así:

Código: Text
  1. casilla* Celula [22][22]
  2.  
De esta forma obtengo un array bidimensional (es decir una matriz) de punteros a célula

E implementando el constructor y el destructor así:
Código: Text
  1. Tablero::Tablero (int i, int j){
  2. limi = i+2;
  3. limj = j+2;
  4. for (int k = 0; k &#60; limi; k++)
  5.    for (int l = 0; l &#60; limj; l++)
  6.    casilla[k][l] = new Celula();
  7. }
  8.  
  9. Tablero::~Tablero(){
  10. for (int i = 0; i &#60; limi; i++)
  11.    for(int j = 0; j &#60; limj; j++)
  12.      delete [] casilla[i][j]
  13. }
  14.  

Ahora el problema lo tengo al querer introducir una célula especializada en alguna casilla determinada. Por alguna extraña razón, sique siendo una célula base... así he implementado (las dos funciones, pero solo voy a mostrar una)
Código: Text
  1. void Tablero::IntroducirEucariota (int posi, int posj){
  2. delete[] casilla[posi][posj];
  3. casilla[posi][posj] = new Eucariota();
  4. }
  5.  

Como comento, la casilla sigue conteniendo un puntero a célula base ¿Cómo lo se?
Dos razones:
1- Al imprimir el tablero, salta el operador de salida de la Célula base, no el de las especializadas.
2.- He debugueado y al terminar de introducir las células especializadas,  si miro las casillas en las que en teoría he metido una célula, me aparece como una base (solo que viva, en lugar de muerta que es como está al llamar al constructor)

Alguna idea de cual puede ser el error? Subiría los nuevos códigos, pero no están en este pc... aunque espero haber descrito el problema con suficientes detalles...
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Karman en Martes 6 de Noviembre de 2007, 01:38
No, no son suficientes detalles... tu problema es un problema de implementación... hay que ver como estás implementando tus clases y las relaciones...

S2
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Martes 6 de Noviembre de 2007, 12:48
Pues entonces, aqui está el código
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Karman en Martes 6 de Noviembre de 2007, 15:23
tu problema es un problema de diseño:

en tablero definís una matriz de células (genéricas) y cuando llamas a que imprima dicha matriz lo más obvio es que te lo imprima como células genéricas (no como especializadas), para que te las imprima como especializadas tenes varias opciones:

1º Que tu célula genérica solo contenga funciones virtuales puras, entonces en cada llamada a imprimir se llamará a las funciones derivadas, pero para eso tendrías que definir un nuevo tipo de célula (célula muerta?) que ocupe los casilleros vacíos<---- Polimorfismo

2º Definir un tercer tipo de célula (casilla por ejemplo) que derive de los dos tipos de células especializadas y que al imprimir analice el tipo y llame a uno u otro método, o imprima '_' <----- Derivación múltiple

3º (como te lo resolví) eliminar de las células especializadas las funciones redundantes y colocarlas únicamente en célula (la especialización es solo la identidad, pero el comportamiento creo que es el mismo, eso creo... cualquier cosa fijate) entonces al llamar a imprimir, la célula genérica se encarga de todo...

S2
Título: Re: Dos Objetos De Clases 'hermanas' Reconociendose
Publicado por: Mararía en Martes 6 de Noviembre de 2007, 19:03
Muchas gracias, al final salió... Resulta que:
1.- ident, tenía que ser de célula, no podía ser de eucariota y procariota... (por este detallito, era por lo que no insertaba los otros tipos de célula)
2.- el operador de salida, no hacía falta implementarlo en las celulas especializadas, con hacerlo en la base y decirle que imprimiera ident, ya estaba.
3.- el método acutalizarestado de célula tenía que ser virtual, ya que cada una de las otras, tenía sus reglas de transición (al menos para morir, para vivir era la misma en ambos casos)

Y ahora, con el permiso de todos, me voy a comer, que ya va siendo hora....