Clases y Librerias
Mi primer duda es con respecto a como definir una clase en c++ de manera que pueda ser usada en una libreria. Esto es lo que tengo:
class barra { int x; int y; int mover(); int inicializar(); int mostrar(); }; //Lo que hago es lo siguiente barra barra1; int barra1::mostrar() { lo que debe hacer }
Eso es una version reducida, el problema es que al llamar la funcion desde el fichero cpp me dice que barra1 no es una clase, entonces, como puedo hacer que los atributos de la clase barra pasen a cada una de los que declare (barra1, barra2, etc...) sin declarar como clase a cada uno de ellos?
Otro problema que se me presenta es que si en el fichero .hpp defino por ejemplo
SDL_Surface *imagen_barra1; int cargar_imagen() { //Cargar imagen y almacenarla en imagen_barra1 }
Al querer llamar la funcion desde el cpp, me dice que no existe imagen_barra1, es decir, que no lo he declarado cuando en realidad lo hize dentro del fichero hpp, he estado leyendo un poco y creo que tengo que definirlo como "extern SDL_Surface *imagen_barra1"
Si alguien pudiera ayudarme con estos problemas estaria agradecido.
Disculpar si no he sido explicito y la falta de acentos, pero estoy en clase y debo hacer esto rapido o el profe me confizca la laptop :p
Saludos.
C plus plus
Bueno, sobre el primer problema, aunque se pueda malhacer de otra forma, lo mejor es crear un ficheros independiente para la declaración de las clases, parece un trabajo extra, pero por la forma de trabajar que tiene C++ en las clases, ahorrá muchos problemas en cuando el proyecto empieze a crecer un poco.
barra.h
barra.cpp
programa.cpp
Tu segunda pregunta no la entiendo
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Segunda Parte
En cuanto a la segunda parte intentaré explicarlo lo mejor que pueda, en el fichero .hpp declaro cómo se cargará la imagen, doy donde se almacenará (SDL_Surface *imagen_barra1).
Sin embargo al cargar desde mi función main, (llamar a la función "cargar_imagen") me dice que imagen_barra1 no se ha definido, cuando ya estaba definido en el fichero .hpp, entonces, no está "conectando" las variables correctamente, pues aunque ya se definió, el compilador no se da cuenta de esto y me marca error.
Es lo mejor que puedo describirlo por ahora. Si aún no lo entiendes, colgaré el código, pero para eso necesito llegar a mi casa xD
Saludos.
PD:Diferencia entre .hpp y .h?
Sí, mejor con el código.
Sí, mejor con el código. pq no sé como está implementado eso que dices.
.hpp se usa a veces para los ficheros de cabecera de c++, yo suelo usar .h para ambos porque así nunca me lío cuando hago "include fichero.h", siempre sé que es .h. Es una cuestión más estética que otra cosa.
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Dudas sobre teoria y otras cosas
Una pregunta sobre librerias, dentro de una libreria se puede hacer un include a otra?
Otra cosa, en tu ejemplo anterior veo que tienes 3 archivos:
Las funciones no se pueden definir dentro de la libreria barra.h?
Ahora, creo que mi segundo problema radica en que estoy trabajando con 2 librerias (relacionado a la pregunta anterior), en una defino clases y funciones de mis objetos, en la otra defino sólo funciones para hacer "x" cosa (cargar archivos, cargar fuente, cerrar fuente, etc...), el problema es que de la segunda libreria necesito hacer "includes" a la primer libreria por cuestiones de variables, creo que es aquí donde radica mi problema y lo estoy haciendo mal.
Bueno, creo que una salida del compilador te aclarará algunas cosas:
funciones.hpp: In function ‘bool cargar_archivos()’:
funciones.hpp:98: error: ‘imagen_barra1’ no se declaró en este ámbito
funciones.hpp:99: error: ‘imagen_barra2’ no se declaró en este ámbito
funciones.hpp:100: error: ‘imagen_bola’ no se declaró en este ámbito
funciones.hpp:101: error: ‘imagen_fondo’ no se declaró en este ámbito
funciones.hpp: In function ‘void limpieza()’:
funciones.hpp:123: error: ‘imagen_barra1’ no se declaró en este ámbito
funciones.hpp:124: error: ‘imagen_barra2’ no se declaró en este ámbito
funciones.hpp:125: error: ‘imagen_bola’ no se declaró en este ámbito
funciones.hpp:126: error: ‘imagen_fondo’ no se declaró en este ámbito
Lo que me dice acerca de que no se ha definido, en realidad esta definido en la otra libreria (objetos.hpp) pero por alguna razón (mal diseño de mi parte, supongo) no las toma en cuenta.
Por último preguntarte si me recomiendas algún IDE pues "vim" no se me acomoda mucho para copiar/pegar código pero vaya que sus colores son chulos y funcionan de 10 :D
Saludos
PD:Por si te ayudara a aclarar algo, aunque supongo ya lo habras notado, estoy trabajando con C++ y SDL
Motivos para usar .h y
Motivos para usar .h y .cpp
-El compilador trata de forma diferente a los ficheros .h y los .cpp.
Tu problema según me cuentas es que haces "includes cruzados", eso es una jodienda que tiene C/C++, y hay que hacer un pequeño "truco", ponerlo tanto en .h como en .cpp. Imaginemos miclase.h y funciones.h, funciones tienes un "#include miclase.h" y miclase. tiene un "#include funciones.h".
Nota: SIEMPRE en todos los .h, poner un "#ifndef", esto hace que sólo se haga un include durante el compilado, sino el compilador hace más de una vez el include y da error de que ya se usó ese .h
miclase.h
funciones.h
miclase.cpp
funciones.cpp
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Avanzamos con esto de las librerias
Después de un rato, creo que ya he arreglado la mayor parte gracias a ti, tengo los ficheros .h, los .cpp y *casi* me compila bien. Ya no me tira las 500 lineas de errores por terminal que me tiraba antes, ahora sólo me tira 6, pero no entiendo muy bien cómo interpretarlas, copio/pego:
/tmp/cc7H8e16.o: In function `main':
pong++.cpp:(.text+0x549): undefined reference to `BarraI::iniciar()'
pong++.cpp:(.text+0x592): undefined reference to `BarraI::mover()'
pong++.cpp:(.text+0x5db): undefined reference to `BarraI::mostrar()'
pong++.cpp:(.text+0x624): undefined reference to `BarraD::iniciar()'
pong++.cpp:(.text+0x66d): undefined reference to `BarraD::mover()'
pong++.cpp:(.text+0x6b6): undefined reference to `BarraD::mostrar()'
collect2: ld devolvió el estado de salida 1
Bueno, la parte que no entiendo es esta "(.text+0xASD)" donde "ASD" es el número y/o letra que corresponde en cada caso.
Dejando esto de lado, creo que lo que estoy haciendo mal es definir las funciones dentro de mi fichero objetos.cpp el cual trabaja con la libreria objetos.hpp
Si he aplicado algo de los ejemplo que has dejado de manera erronea, te agradecería me dijeras para poder corregirlo.
Saludos.
Uhmm
Bueno, primero veo que tienes una clase BarraI y otra BarraD, lo cual no hace falta. Haz una clase Barra y luego creas una variable objeto barrai (con posición a la izda.) y otra barrad (con pos a la dcha.). Pero dejando eso aparte.
-objetos.cpp, es muy genérico, hay que poner nombre_de_la_clase.cpp y nombre_de_la_clase.h, uno por clase. Si el error te lo diera en objetos.cpp te diría que te falta el "#include objetos.h", pero te lo da en pong++.cpp, así que deduzco que no es un fichero que contiene el código de la clase, en cuyo caso habría que usar la sintaxis BarraI.iniciar(), etc. Los dos puntos dobles "::" se usan para indicar que estás definiendo el método/función iniciar() se refiere a BarraI, que no es una función "suelta".
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Casi compila
Tengo dos clases, izquierda y derecha, pues aún no se me ocurre cómo mostrar 2 imagenes con una sola clase, ahora hablando de mostrar imagenes, eso es lo que no me permite compilar.
Desde el problema anterior, simplemente hize un #include "barra.cpp" pues no lo tenia. Eso me llevo a declarar:
Los cambie de main() al fichero barra.cpp. Y a su vez cambie:
esto a su vez, me llevo a otro error, copio/pego del compilador:
In file included from pong++.cpp:6:
objetos.cpp: In member function ‘int BarraI::mostrar()’:
objetos.cpp:19: error: el argumento de tipo ‘int (BarraI::)()’ no coincide con ‘int’
objetos.cpp: In member function ‘int BarraD::mostrar()’:
objetos.cpp:35: error: el argumento de tipo ‘int (BarraD::)()’ no coincide con ‘int’
A raíz de esto, lo volví a su estado anterior, pero me di cuenta que causa esto:
barra.cpp: In member function ‘int BarraI::mostrar()’:
barra.cpp:19: error: expected primary-expression before ‘.’ token
barra.cpp:19: error: expected primary-expression before ‘.’ token
De acuerdo a lo que he entendido con el final de tu comentario anterior, deduzco que lo correcto es dejarlo de esta forma:
Bueno, entonces, esto causa que los argumentos no coincidan, la verdad es que para ser sincero no tengo ni idea a lo que se refiere, pues regresa 0 al final y tanto getX cómo getY son de tipo int.
Espero que no te hayas perdido al leer este comentario, que he tratado de hacerlo lo más claro posible.
Por cierto, si comento la función mostrar_imagen, compila sin problemas, pero obviamente no muestra imagenes, quiza esto debería (o más bien debo) hacerlo directamente desde main en lugar de declararlo en otro fichero, probaré y si obtengo algún resultado positivo o negativo lo posteo.
Saludos.
Buf, aquí tienes un lio de
Buf, aquí tienes un lio de clases y funciones.
Sobre " no se me ocurre cómo mostrar 2 imagenes con una sola clase". Estás un poco liado.
Tú te creas una clase barra, que tiene unos datos, digamos posX, posY, color, tamaño, etc.
Te creas 2 objetos barraizda y barradcha. de la clase barra: barra barraizda, barradcha;
A cada una le asignas una posición, imagen que le correspone, y más datos si tuviera, ten en cuenta que la programación está dentro de las clases, son sus métodos los que tienen que hacer todo. Por ejemplo:
Ojo con el método barraI.setImage("barra_izda.png"), lo que tienes que hacer en el método setImage, es definirlo en .cpp, ya que es complejo y no se generará online, es crearte una SDL_Image a partir de ese fichero y lo guardas en un dato de la clase, por ejemplo m_SDLImage (yo uso m_ para diferenciar las variables miembro internas, pero eso es cuestión de estilo, usaría m_X, m_Y, etc.)
De tal forma que cuando llames al método mostrar(). usarías m_Image que ya contiene el SDL_Image, ahorrandote la función "mostrar_imagen", que en realidad es lo mismo que el método. y estás llamando a una función que envia como parámetro datos de un objeto que en realidad no te hace falta, porque eso mismo lo puedes hacer en el método mostrar. No sé si se me entiende.
Creo que el problema lo tienes porque usas funciones sueltas mezcladas con métodos y estas no pueden acceder a las partes privadas del objeto a no ser que las declares como friend. Pero en este caso, creo que es liarse, es mejor hacerlo todo en los método, no veo necesidad de poner funciones friend.
Siento no haberme explicado mejor. Un saludo
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Petición
GorristeR, si tienes tiempo, te importaría poner un ejemplo de cómo cargarias tú una imagen, por que sinceramente, en estos momentos, estoy que no doy más, completamente liado, ya no encuentro pies ni cabeza a ninguno de mis ficheros, estoy tratando de hacer una combinación entre lo que tu me has dicho, los tutoriales de lazy foo, y el libro de Alberto Garcia Serrano, pero simplemente no se me da, cada vez termino con errores peores, uno trás de otro, intento basarme en sources de otros pero simplemente no me da el resultado esperado y termino liando más los ficheros, creo que iniciaré todo de 0 pues ya no le hayo forma a nada...
De cualquier forma, gracias por tu tiempo y ayuda, de verdad los aprecio.
Saludos.
Edito:
Después de dormir, irme a la escuela, y regresar a mi casa, me doy cuenta de que mis ideas ya están más ordenadas, y entiendo mis ficheros perfectamente, ya he comenzado la "remodelación" y creo que por fin he logrado "digerir" lo que me has dicho.
Gracias por todo!