Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Cuidado Con Los Objetos (poo)

Iniciado por cemar, 06 de Noviembre de 2004, 03:30:10 AM

« anterior - próximo »

cemar

 Hola.

Estoy escribiendo un juego de parchis en c++ usando POO, y me he encontrado el siguiente problema:

Necesito que la clase cFicha tenga un atributo que sea un puntero a la casilla en la que está, y viceversa (la clase cCasilla tiene un puntero a la ficha que contiene).

Cada clase la tengo repartida en dos ficheros, el .h y el .cpp. Pues bien, no soy capaz de compilar el código fuente.

Ya he observado en otras ocasiones que cuando se forma un bucle de #includes algo no funciona bien. Pero no sé como solucionarlo. Os pongo un esquema de lo que tengo por si me pudierais echar un cable.

En el archivo Casilla.h tengo:
#if !defined(_definicion_de_cCasilla_)
#define _definicion_de_cCasilla_
#include "Ficha.h"
class cCasilla
{
private:
 cFicha* pFicha;
....
}
#endif

En el archivo Ficha.h tengo:
#if !defined(_definicion_de_cFicha_)
#define _definicion_de_cFicha_
#include "cCasilla.h"
class cFicha
{
private:
 cCasilla* pCasilla;
.....
}
#endif

He probado tambien con la directiva #ifndef del precompilador y pasa lo mismo.

Muchas gracias.
Cemar

BeRSeRKeR

 Supongo que el punto y coma al final de la declaración de las clases se te habrá olvidado ponerlo al escribir el código en el foro...

En cualquier caso, puedes utilizar "forward declaration". Sería algo así:

Casilla.h
#ifndef CASILLA_H
#define CASILLA_H

class cFicha;    // <- Forward declaration

class cCasilla
{
public:
   cCasilla();
private:
   cFicha *m_pFicha;
};

#endif


Casilla.cpp
#include "Casilla.h"

cCasilla::cCasilla()
{
   m_pFicha = 0;
}


Ficha.h
#ifndef FICHA_H
#define FICHA_H

class cCasilla;    // <- Forward declaration

class cFicha
{
public:
   cFicha();
private:
   cCasilla *m_pCasilla;
};

#endif


Ficha.cpp
#include "Ficha.h"

cFicha::cFicha()
{
   m_pCasilla = 0;
}


Supongo que eso debería funcionar.

Leete esto también y busca en Google más información sobre "forward declaration".

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

joramo

 Ay!! Ay!! Carlitos Carlitos, que problemas tenemos con los objetos  (uoh)  si es que no se puede uno coger un TFC tan chungo jejeje. Por cierto a ver para cuando lo presentas que ire a ver la exposicion y me preparare un par de preguntas chungas para hacerte  :D  :D

Venga ya hablamos. Ta luesss

cemar

 Hola. Gracias BeRSeRKeR.  :)

El punto y coma del final sí que lo tenía puesto en el código fuente, aunque se me olvidó escribirlo en la explicación.

He probado lo que me dijiste y sigo teniendo problemas. Ahora me da error al llamar a un método de uno de esos objetos dentro del otro. El código lo tengo tal y como me comentaste en el post anterior, y en el archivo Casilla.cpp tengo entre otros:

#include "Casilla.h"

cCasilla::cCasilla()
{
  m_pFicha = NULL;
}

void cCasilla::PosicionarFicha(cFicha *pFicha)
{
  m_pFicha = pFicha;
}

bool cCasilla::PuedeMover()
{
  ...
  int Color = m_pFicha->DimeColor();      // AQUI ME DA EL ERROR
  ...
}

...


En la línea donde llama al método DimeColor de m_pFicha, Visual C++ 6 me da los siguientes errores :
 - use of undefined type 'cFicha'.
 - left of '->DimeColor' must point to class/struct/union.

Entiendo que el problema es que no reconoce que ese método corresponde a esa clase, pero no encuentro información de como solucionarlo. Seguro que es una tontería.

Muchas gracias.
Cemar

cemar

 Hola de nuevo.

Lo acabo de solucionar  (ole) . He añadido a cada fichero .cpp el include del .h de la otra clase. Es decir, quedaría:

Casilla.h
#ifndef CASILLA_H
#define CASILLA_H

class cFicha;    // <- Forward declaration

class cCasilla
{
public:
  cCasilla();
  void PosicionarFicha(cFicha *pFicha);
  bool PuedeMover();
private:
  cFicha *m_pFicha;
  ....
};
#endif


Casilla.cpp
#include "Casilla.h"
#include "Ficha.h"   // AÑADIDO

cCasilla::cCasilla()
{
  m_pFicha = 0;
}

void cCasilla::PosicionarFicha(cFicha *pFicha)
{
 m_pFicha = pFicha;
}

bool cCasilla::PuedeMover()
{
 ...
 int Color = m_pFicha->DimeColor();
 ...
}
...


Ficha.h
#ifndef FICHA_H
#define FICHA_H

class cCasilla;    // <- Forward declaration

class cFicha
{
public:
  cFicha();
  int DimeColor();
private:
  cCasilla *m_pCasilla;
...
};
#endif


Ficha.cpp
#include "Ficha.h"
#include "Casilla.h"  // AÑADIDO

cFicha::cFicha()
{
  m_pCasilla = 0;
}
...


Muchas gracias. Hasta luegoo!!  :D
Cemar.


BeRSeRKeR

 En ese caso, en Casilla.cpp haz un include a Ficha.h:

#include "Casilla.h"
#include "Ficha.h"


Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

cemar

 Hemos pensado los dos lo mismo  :rolleyes:  . Muchas gracias por ser tan rápido en contestar. Ahora sí que me voy a dormir.

Saludos.

BeRSeRKeR

 Ah, no me había dado cuenta que ya te habías contestado a tí mismo. :lol:
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

shephiroth

 Muy buenas.

Lo que voy a comentar es una problematica que tiene el compilador .net........si lo quereis comprobar hacer una copia, puesto que haremos algunas modificaciones.

Al principio en mis proyectos, utilizaba un .h solamente, en el que declaraba primero las cabeceras de las funciones, y debajo el codigo propio de las funciones, de forma que le estructura de archivos me quedaba:

ejer1.cpp
ejer1.h
clasea.h
claseb.h

Basicamente en el ejer1.h declaraba todo, includes y demas. No me hacia falta ni utilizar los #ifndef.

Un dia despues de ver como lo hacíais vosotros (XXX.cpp y XXX.h) decidí hacer lo mismo. Asi que haciendo una copia pille mi clasea.h, y todo el codigo de funciones moverlo al clasea.cpp. Este fue el principio de mis problemas. En el cpp tuve que incluir el .h y me empezo a decir que habia objetos no declarados (utilizaba la claseb) y que la clasea estaba declarada 2 veces.

Despues de pensarlo mucho llegue a la conclusion de que es un problema del compilador. No tiene establecido que .cpp es el primero, y lo que hace es buscar cual tiene que compilar primero. Es decir, primero empieza en ejer1.cpp y comprueba si todo anda bien. Luego empezaría por clasea.cpp, y da problemas por todos lados puesto que ya estaba incluido antes xDD

Yo creo que el problema que os da[ba] es ese >_<

Buffon

 El problema de meterlo todo en un cpp es la reusabilidad.

por que necesitas tener que recompilarlo todo si solo haces una pequeña modificacion?

no se puede juntar la velocidad con el tocino, me explico, no es lógico que teniendo que usar esto:



Clase:     cTablero
Def:         Define la estructura de un tablero de ajedrez
Atrib:       .....
Métodos: ......

Clase:     cEstadísticas
Def:        Define las estadísticas sobre los movimientos de los jugadores
Atrib:      .....
Métodos .....


pues no es lógico meter estas dos clases en el mismo cpp por que sus funcionalidades son totalmente independientes, como mucho estadística se comunicará con un controlador que recoja datos de Tablero, pero nada más.

la POO se basa en una de sus características en eso ;)

jelorol

 Lo que voy a decir no tiene nada que ver con la programación, pero, ¿has tenido en cuenta que en una casilla puede haber más de una ficha? ¿o estás aplicando reglas simplificadas?

cemar

 Hola.

Realmente doy la posibilidad de que haya dos fichas por casilla. Simplemente quería exponer el problema de la forma más sencilla posible.

Hasta luego!!

Pogacha

 Para mas de una ficha por casilla sugiero listas enlazadas al mejor estilo Pogacha!!!

class cFicha {
 cFicha *Siguiente;
 friend cCasillero;
 cCasillero *Casillero;
public:
 cFicha() { Siguiente = NULL; };
 void Quitar(void)
 {
     if(cCasillero->Fichas==this) {cCasillero->Fichas=Siguiente; return; }
     for(cFicha *f=Casillero->Fichas; f; f=f->Siguiente)
               if(f->Siguiente==this) f->Siguiente=Siguiente;
 }
};

class vCasillero {
  cFicha *Fichas;
  friend cFicha;
public:
  cCasillero() { Fichas = NULL; };
  void Poner(cFicha *f) { f->Siguiente=Fichas; Fichas=f; f->Casillero=this;}
  void Quitar(cFicha *f) { f->Quitar(); } // para que la puedas quitar de los dos lados.
}


Obviamente esto asi no anda, hay que usar el foward reference.
Esto en realidad fue un ejercicio de auto evaluacion, para ver en cuanto tiempo lo podia escribir.
Espero que le sirva a alguien.
Saludos






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.