Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





#include y #ifndef

Iniciado por davidgf, 21 de Noviembre de 2007, 09:29:58 PM

« anterior - próximo »

davidgf

Hola! Otra vez voi a dar guerra...

Pues mi marea sucia, guarra i tocina de programar (acostumbrado al VB) me a tocado las narices con los includes... i para evitar que se me includeen inifinitas veces le pongo a todos los headers un #ifndef #endif

Pero funciona con todos menos con uno... vaiaaa... Vosotros que le dais al c++ de verdad sabreis decir donde meto la pata:

cMusicEngine.cpp (clase que manda)


#include "cStreamOGG.h"
#include <dsound.h>
[...]


cStreamOGG.h (la clase que hace el trabajo sucio)


#ifndef CSTREAMOGG_H_INCLUDED
#define CSTREAMOGG_H_INCLUDED

#include "auxiliar.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"

#ifndef STREAMOGG_DEFINED
const int STREAMOGG_BUFFER_SIZE = 4096;

class cStreamOGG {
public:
[...] la clase continua


i en el codigo del cMusicEngine.cpp me dice que no encuentra la clase cStreamOGG, cuando uso un include bien grande hacia ella ademas de ponerle una proteccion para que no se incluya varias veces (porque hay muchos archivos que tienen muchos includes cruzados)

Alguna ayudita para un pobre ??? xD

Gracias!
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

TiRSO

Cita de: "davidgf"
#ifndef STREAMOGG_DEFINED
const int STREAMOGG_BUFFER_SIZE = 4096;

Ahí te falta un #endif. Supongo que será por eso.

davidgf

Perdón, es que no he escrito pero al final hay dos #endif (uno para la inclusion del H i otro para la defincion de la clase)..

No se que puede ser...
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

Pogacha

Otra posibilidad de error, ya que dices que eres nuevo en C++, y pasa muy seguido es:

a.h#include "c.h"

class a {
 f(c* _c) { _c->f(); }
};

b.h#include "a.h"

class b {
 f(a* _a) { _a->f(); }
};

c.h#include "b.h"

class c {
 f(b* _b) { _b->f(); }
};


main.cpp#include "a.h"
#include "b.h"
#include "c.h"

Result: Error class a undefined!

O bien te puede decir: tratando de usar la clase a la cual no esta definida. Si sigues el camino a.h -> b.h -> c.h -> skip a.h -> define class c -> use of a ( a has never been defined )

Lo escribi en un ciclo triple por que en uno doble se nota pero no se entiende.

Para solucionarlo se usa forward declarations.

Saludos

davidgf

I como se hace eso?? Es que es muy muy raro... no entiendo porque pasa...

He probado a hacer lo de esta web http://www.adp-gmbh.ch/cpp/forward_decl.html pero nada... Sigue igual
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

Pogacha

¿En que archivo te dice que no se encuentra la clase?
Te tiene que decir elarchivo.h included in elcpp.cpp.
Te vas a ese .h y sacas el include .h donde esta la declaracion de la clase y dejas en su lugar class laclase;
Luego de esto en ese .h no podras usar esa clase, tan solo hacer referencia a punteros de la misma. Hacer Foo(laclase* a); en la cabecera y luego declarar la funcion en el cpp es valido pero no hacerlo inline tipo: Foo(laclase* a) { a->f(); }  

Si hay constantes o definiciones involucradas las puedes sacar y poner en otra cabecera.

Muchas veces tienes que buscar como seria la mejor forma de hacerlo, para que te quede mas prolijo el codigo.

davidgf

Ufff me cuesta de entender.

Me parece que mi estructura está mal. Yo tengo por cada clase un cpp con el codigo i la declaracion (metida entre ifndefs) i otro .h con la delcaracion de la clase solamente (metida tambien entre ifndefs)

Asi incluyo desde otro cpp o otro .h i la uso

Cómo debería ser el código? Todo .h? Cuando uso .h y cuando .cpp? QUe diferencia notable hay?

Mil gracias por tu ayuda Pogacha!!!
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

Pogacha

La palabra declarar se me confunde a mi tambien  :oops:

la idea de como usar .h y .cpp

laclase.h
#ifndef LACLASE_H
#define LACLASE_H
#include "necesarios_para_esta_cabecera.h"
const tipo constante = valor;

class otra_clase_que_esta_definida_en_otro_h; // esto es un forward

class laclase {
  tipo miembros;
 public:
  laclase();
  ~laclase();
  void f(otra_clase_que_esta_definida_en_otro_h* p);
  static void f2();
};

#endif


laclase.cpp

#include "laclase.h"
laclase::laclase()
 : miembro(valor_por_defecto)
{
 ...
}

laclase::~laclase()
{
 ...
}

void laclase::f(otra_clase_que_esta_definida_en_otro_h* p)
{
  p->Funcion_De_La_Otra_Clase();
}

void laclase::f2()  // funcion estatica, miembro no es accesible ;P
{
 ...
}


En el h le dices al compilador como es la forma de la clase, ademas de constantes afines.
En el cpp le dices al compilador que hace la clase.

Esa es la idea.

En el .h puedes agregar funciones inline:

class laclase {
f(laotraclase* a) { a->f(); }
};

pero aqui es donde ese error sucede a veces entonces tienes que tener mucho ojo.

En el cpp no hay que poner el ifndef ni el define, esos son tan solo para el .h, en cada cpp se tienen que volver a leer los .h por eso es que los sacas a otro archivo, para compartir esa parte del codigo entre muchos cpps.

Saludos

EDITO:
En el .h va la declaracion y en el .cpp la implementación :P

TiRSO

Yo no entiendo para qué pones dos #ifndef anidados en el .h. No lo había visto en mi vida y en principio no creo que haga falta.

tamat

yo tambien creo que hay un ifndef que no está bien cerrado
Por un stratos menos tenso

Tei

No voy al problema, porque no se cual es.
Solo aporto un comentario.

En lugar de escribir esto:
Citar
#ifndef CSTREAMOGG_H_INCLUDED
#define CSTREAMOGG_H_INCLUDED

#include "auxiliar.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"

Puedes escribir esto:
Citar
#include "auxiliar.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"

#ifndef CSTREAMOGG_H_INCLUDED
#define CSTREAMOGG_H_INCLUDED

Ya que todos esos .h van a estar protegidos contra doble inclusión. No hace falta re-protegerlos dentro del ifndef.

Quizás puedas dibujar un arbolito de tus inclusiones. Para revelar un problema de definición circular como comenta un compañero.

fiero

Cita de: "davidgf"Ufff me cuesta de entender.

Me parece que mi estructura está mal. Yo tengo por cada clase un cpp con el codigo i la declaracion (metida entre ifndefs) i otro .h con la delcaracion de la clase solamente (metida tambien entre ifndefs)

Asi incluyo desde otro cpp o otro .h i la uso

Cómo debería ser el código? Todo .h? Cuando uso .h y cuando .cpp? QUe diferencia notable hay?

Hola David,

¿Dices que tienes en el CPP el código y la declaracion? ¿Y despues en el H solo la declaración?

Si has utilizado las mismas constantes CSTREAMOGG_H_INCLUDED en el CPP y en el H, seguramente la clase se haya incluido en el CPP, y luego el H se lo salta, por lo que ya no se declara la clase donde hayas incluido ese .H

Debes eliminar las declaraciones de los CPP. Para eso están los #include "fichero.h". Es cierto que se pueden declarar clases en cualquier sitio, pero si tienes poca experiencia, sigue siempre la norma: declaraciones en los .H y código en los .CPP

saludos
www.videopanoramas.com Videopanoramas 3D player

davidgf

Vale! Ya lo he hecho y ha quedado todo bastante mejor.

Por cierto, reabro el tema del famoso "Mutithreaded Debug", esa opción del VS que hacía que Cal3D no me fuera bien y que consigue ahora que la version Release de mi juego no funcione. Si pongo en la lib del Cal3D "MT Debug" hasta ahora funcionava. Pero ahora al añadir OGG, si no añado MT Debug al proyecto principal no funciona.

Alguien abes porqué c**o no va???? Es una maldita opción al compilar!!!

Gracias a todos por la ayuda!! No si al final aprenderé i todo....

EDITO: AL final va TODO!!! Recompilé todo a saco desde 0. Ahora todo va correctamente!!! Weee!

Una preguntita de nada. Si uso Cal3D he hecho dos : la release i la debug. I a cada parte de mi juego le asigno una en las opciones del proyecto. Es necesario? o mi version debug puede ir con la release de Cal3D?? No se si lo he dicho bien...

I además es curioso poruqe el VS sabe donde estan los archivos i al debugear te entra automaticamente en los archivos de las DLLs que usas... Eso mola, pero lo hace siempre? Estoy flipando... Yo que pensava que el VS era cutrillo...

Millones de gracias a todos!!!!
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)

shephiroth

Buenas.

Hace ya un tiempo que me he pasado a java (por la carrera) pero dentro de poco tendre que volver al c, asi que este tema me interesa. Ya que veo que mencionais las referencias circulares, me pregunto si esto funcionaria:

resuelve_circular.h:

#ifndef _CLASS_CIRCULAR_
#define _CLASS_CIRCULAR_
class a;
class b;
class c;
#endif


a.h:.

#include "resuelve_circular.h"
#ifndef _CLASS_A_
#define _CLASS_A_
class a{public b dameb();}
#endif


b.h:

#include "resuelve_circular.h"
#ifndef _CLASS_B_
#define _CLASS_B_
class b{public c damec();}
#endif


c.h:

#include "resuelve_circular.h"
#ifndef _CLASS_C_
#define _CLASS_C_
class c{public a damea();}
#endif


Y alla donde tengas que utilizar cualquiera de las clases incluir el .h auxiliar en vez de los .h de las clases directamente.

davidgf

No lo se pero diria que no...

Yo he usado estas reglas:

Declarar en .h e implementar en cpp como me dijeron muy bien todos aqui.

En los .h (declaraciones) no incluir nada (que no sea string.h, windows... etc) y usar class LaClase; en vez de ello.

Luego en los cpp que usan las classes incluir los .h. Me parece que es mejor poner todos los includes en cada cpp (aunque te repitas)

I en los .h una proteccion para evitar la doble inclusion/declaración.

No se si me explico. Pero a mi me funciona; muy bien además. ;)
Tàrraco: una aventura por la Tarragona romana (http://tarraco.davidgf.net)






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.