domingo, 8 de julio de 2007

Referencias cruzadas entre dos clases

En mi diseño, los métodos de una clase tienen que poder llamar a los métodos de una segunda. Los métodos de la segunda clase tienen que poder llamar a los métodos de la primera.
La solución para este problema que se me ha ocurrido es poner un puntero a la clase que queremos llamar como parte privada. Uno de los métodos públicos de la clase se encargará de darle el valor adecuado a ese puntero. Supongamos una cabecera “clasejuego.h”:

#include "claseescena.h"

class claseJuego
{
private:
claseEscena * punteroEscena;
[...]
public:
// class constructor
claseJuego();
// class destructor
~claseJuego();

// Asigna la dirección del objeto Escena en el Juego
void asignaEscena(claseEscena * nuevoPunteroEscena);

// Con este método cambio propiedades del objeto Escena
void cambiaEscena(int a, int b);
[...]
};

En “claseescena.h” el código sería muy parecido.
Nosotros crearíamos las instancias de los objetos e inmediatamente después llamaríamos a asignaEscena y a asignaJuego tal que así:

#include "clasejuego.h"
#include "claseescena.h"

int main(int argc, char *argv[])
{
claseJuego * punteroJuego;
claseEscena * punteroEscena;

punteroJuego = new claseJuego;
punteroEscena = new claseEscena;

punteroJuego->asignaEscena(punteroEscena);
punteroEscena->asignaJuego(punteroJuego);
[...]
}

Parece correcto, ¿verdad? Pues esto no compila. No se pueden hacer includes cruzados por que no se pueden declarar dos tipos a la vez. Por muchos includes que se pongan en las cabeceras, el compilador recibe las declaraciones de una en una. Siempre se encotrará con que se hace referencia a un tipo todavía no declarado. Así que investigando sobre este problema he encontrado que se pueden hacer declaraciones de tipos por adelantado. Así en “clasejuego.h”:

#include "claseescena.h"

class claseEscena; // referencia por adelantado de un tipo
class claseJuego

{

private:
claseEscena * punteroEscena;
[...]

Igual en la otra cabecera.
Hay otra soluciones para este problema, pero esta me parece la más fácil. Ahora, a otra cosa :)

No hay comentarios: