Including .h classfiles

Started by
18 comments, last by eckbw 20 years, 9 months ago
What you say you''re trying to do is now correct. What you have is a bug where you''re not doing what you think you are and you need to show us the actual code rather than the theoretical code.
Advertisement
If you´re wondering what it really is I´m working with I´m doing a 2D space shooter and I´ve made these abstract baseclasses called CGeneral and CGeneralManager and then I have CEnemy, CEnemyManager, CShot, CShotManager, CPlayer and CPlayerManager that are all subclasses of CGeneral and CGeneralManager. They may be different things but they´re all 2D objects represented on the screen with approx the same attributes but just different ways to update and render themselves.

Anyway I kinda solved it now by just putting them all in a single .h file. It´s working fine now, don´t know what was wrong earlier... but now the .h file is huge and rather messy... but now that it´s working I´m tempted to just leave it there and treat it like a black box so I don´t mess something up again.
Taking a look at the source code:
#ifndef SOMECLASS_H#define SOMECLASS_H#include "someotherclass.h"class SomeClass;class SomeClass : public SomeOtherClass#endif


Do you really need class SomeClass; above the class SomeClass : public SomeOtherClass? That would seem to me, to be what is causing the "already defined" errors :/

If I am wrong, why would you need to have a class prototype?


-=-
"Boy? Girl? It does not matter, all that matters is power, and beauty is power. I am beautiful, so I have power and that is all that matters."
Got Immortality?
[ Six Hour Game Contest | ( Thread | Blog | Wiki | 6hour Bio ) ][ Website | (Blog | Gallery ) ]
Well, I think I tried that too, but it generates error "class SomeClass was not declared at this scope" or something like that. And when I try to put the the class prototype of the baseclass in there I get a error "class BaseClass has incomplete type". So I just put everything in a single .h file and now it´s working great.
quote:Original post by eckbw
now that it´s working I´m tempted to just leave it there and treat it like a black box so I don´t mess something up again.


Don''t be afraid. This is something that everyone has to learn to do correctly. It''s not hard once you understand it.

You need to come up with a small example that doesn''t work: Take copies of two of the files that were causing the error. Make a new .cpp file and just include those headers, strip them down to a bare minimum to still get the error and post them here. Once it''s fixed and you understand what you''ve been doing wrong you can go and change the real files. We''ll help and you''ll be very happy once it''s done!

Pete
Alright, I tried to separate them again, but I get the same compiler errors as before. Guess I must be doing something wrong when including the files or something. Here´s what they look like:

In "generalclass.h"

#ifndef __GENERALCLASS_H__#define __GENERALCLASS_H__class CGeneral;class CGeneralManager;class CGeneral{public:   inline CGeneral(void): m_speed(0), m_deathAge(1.0f), m_age(-1.0f), m_health(-1)   {       m_emitterPosition[0] = 0.0f; m_emitterPosition[1] = 0.0f;      m_destPosition[0] = 0.0f; m_destPosition[1] = 0.0f;      m_curPosition[0] = 0.0f; m_curPosition[1] = 0.0f;      m_colWidth = 0.0f; m_colHeight = 0.0f;      m_colWidthOffset = 0.0f; m_colHeightOffset = 0.0f;      m_lethality = LETHAL_NONE; m_typeOfRender = NORMAL_RENDER;      m_startSize = 0.0f; m_endSize = 0.0f; m_sizeCounter = 0.0f;   };   inline ~CGeneral(void){ };      float m_emitterPosition[2];  // ursprunglig x/y position   float m_destPosition[2];    // önskad x/y destination   float m_curPosition[2];    // aktuell position   int m_speed;            // objektets hastighet   float m_deathAge;      // ålder då det dör   float m_age;          // hur länge det har levt      float m_startSize, m_endSize; // objektets start/slut storlek   float m_sizeCounter; // för att beräkna hur storleken ska ändras under livscykeln   int m_health;      // objektets hälsa   float m_colWidth, m_colHeight;  // för    float m_colWidthOffset, m_colHeightOffset; // kollisionsberäkningar   int m_lethality;      // vad objektet kan kollidera med   int m_typeOfRender;   // hur objektet ska ritas upp   int m_bitmap, m_bitmapWidth, m_bitmapHeight;  // vilken bitmap som används      // skapar ett objekt med angivna attribut från ManagerKlassen   virtual inline void Create(CShotManager *pSM){ };   virtual inline void Create(CEnemyManager *pEM){ };   // uppdaterar objektet   virtual inline void Update(float secCounter, CPlayerManager& PM, CEnemyManager& EM){ };   virtual inline void Update(float secCounter, CPlayerManager& PM){ };      // kontrollera kollisioner   virtual inline void CheckForCollision(CPlayerManager& PM, CShotManager& SM){ };   virtual inline void CheckForCollision(CPlayerManager& PM){ };};class CGeneralManager{public:   inline CGeneralManager(void): m_speed(0), m_health(-1), m_life(1.0f), m_lastUpdate(0.0f)   {       m_emitterPosition[0] = 0.0f; m_emitterPosition[1] = 0.0f;      m_destPosition[0] = 0.0f; m_destPosition[1] = 0.0f;      m_colWidth = 0.0f; m_colHeight = 0.0f;      m_colWidthOffset = 0.0f; m_colHeightOffset = 0.0f;      m_lethality = LETHAL_NONE; m_typeOfRender = NORMAL_RENDER;      m_startSize = 0.0f; m_endSize = 0.0f; m_sizeCounter = 0.0f;   };   inline ~CGeneralManager(void){ };      float m_lastUpdate;       // senaste tiden objektet blev uppdaterat   float m_emitterPosition[2];       float m_destPosition[2];   int m_health;   float m_life;   float m_startSize, m_endSize;   float m_sizeCounter;   int m_bitmap, m_bitmapWidth, m_bitmapHeight;      float m_colWidth, m_colHeight;   float m_colWidthOffset, m_colHeightOffset;   int m_speed;   int m_lethality;   int m_typeOfRender;      // ganska uppenbart vad dessa gör      inline void SetEmitterPos(const float x, const float y){ m_emitterPosition[0]=x; m_emitterPosition[1]=y; };   inline void SetDestPos(const float x, const float y){ m_destPosition[0]=x; m_destPosition[1]=y; };   inline void SetSpeed(const int speed){ m_speed = speed; };   inline void SetBitmap(const int surfIndex, const int width, const int height){ m_bitmap=surfIndex; m_bitmapWidth=width; m_bitmapHeight=height; };   inline void SetLife(const float sec){ m_life=sec; };   inline void SetLethality(const int lethality){ m_lethality = lethality; };   inline void SetTypeOfRender(const int renderType){ m_typeOfRender = renderType; };   inline void SetHealth(const int health){ m_health = health; };      // döda alla objekt   virtual inline void DestroyAll(void){ };   // uppdaterar/skapar objekt   virtual inline void Update(void){ };   virtual inline void Update(float sec, CPlayerManager& PM, int flag){ };   virtual inline void Update(float sec, CPlayerManager& PM, CEnemyManager& EM, int flag){ };   // ritar alla levande objekt   virtual inline void Render(void){ };};#endif // __GENERALCLASS_H__


Sorry, comments are in Swedish but you can make out by the function and variable names what they do.

In "playerclass.h"

#ifndef __PLAYER_H__#define __PLAYER_H__#include "generalclass.h"#include "shotclass.h"#include "enemyclass.h"// some defines and typedefsclass CPlayerManager;class CPlayerManager : public CGeneralManager{private:   float m_curPosition[2];   // x/y position på skärmen   player_dir_t m_dir;     // skeppets frame   player_fire_t m_fire;   // typ av vapenpublic:   CPlayerManager(void);   ~CPlayerManager(void);      float GetX(void);   float GetY(void);   void SetPosition(const float x, const float y);      virtual void Render(void);   virtual void Update(void);};// inline class bodies#endif // __PLAYER_H__


In "shotclass.h"

#ifndef __SHOT_H__#define __SHOT_H__#include "generalclass.h"#include "playerclass.h"#include "enemyclass.h"// some defines and typedefsclass CShot;class CShotManager;class CShot : public CGeneral{private:   CShotManager *parent;public:   CShot(void);   ~CShot(void);   virtual void Create(CShotManager *pSM);  // skapar ett skott   virtual void Update(float secCounter, CPlayerManager& PM, CEnemyManager& EM); // uppdaterar skott   virtual void CheckForCollision(CPlayerManager& PM, CEnemyManager& EM); // kontrollera om skottet träffade något};class CShotManager : public CGeneralManager{private:   CShot m_shots[SHOT_MAX_NUM];public:   CShotManager(void);   ~CShotManager(void);     virtual void DestroyAll(void); // döda alla skott   virtual void Update(float sec, CPlayerManager& PM, CEnemyManager& EM, int flag); // uppdaterar/skapar skott   virtual void Render(void);  // ritar alla levande skott};// inline class body definitions#endif // __SHOT_H__


In "enemyclass.h"

#ifndef __ENEMY_H__#define __ENEMY_H__#include "generalclass.h"#include "shotclass.h"#include "playerclass.h"// some definesclass CEnemy;class CEnemyManager;class CEnemy : public CGeneral{private:   CEnemyManager *m_parent;public:   CEnemy(void);   ~CEnemy(void);      int m_AItype; // fiendens AI typ      virtual void Create(CEnemyManager *pEM);   // skapar en fiende   virtual void Update(float secCounter, CPlayerManager& PM);     // uppdaterar fienden   virtual void CheckForCollision(CPlayerManager& PM);};class CEnemyManager : public CGeneralManager{public:   CEnemyManager(void);   ~CEnemyManager(void);      CEnemy m_enemy[ENEMY_MAX_NUM];   int m_AItype;      void SetAI(int AItype);        virtual void DestroyAll(void); // döda alla fiender   virtual void Update(float sec, CPlayerManager& PM, int flag); // uppdaterar/skapar fiende   virtual void Render(void);  // ritar alla levande fiender};// inline body definitions#endif // __ENEMY_H__
In "generalclass.h", lose the "class CGeneral; class CGeneralManager;" lines and in "playerclass.h", lose the "class CPlayerManager;" line as these don''t do anything for you.

We can still tell that this is not a complete example as you use the type ''player_dir_t'' and that''s not defined anywhere. Maybe it all depends on the order in which you include the files, but that is a bad thing. In fact, with that in mind, it''s impossible to fix your code as there are lots of identifiers that mean nothing without seeing more files. So it could be something in those files that is causing the problem.

Some short hints though: only declare forward declarations for classes you need, only #include a class if you can''t use a forward declaration, never rely on a certain inclusion order (instead always force that to happen with #includes) and don''t bother forward declaring a class you''re about to define anyway.

It might also help you to read my "organizing files in C++" article, which is linked in my signature somewhere.

[ MSVC Fixes | STL Docs | SDL | Game AI | Sockets | C++ Faq Lite | Boost
Asking Questions | Organising code files | My stuff | Tiny XML | STLPort]
Ok, great article, but I already knew most of it. I really can´t see why my code doesn´t work. It should work. I have 35 other source files in the project and only those 4 files are causing trouble. It was working when I just had player, shot and enemy as different classes in three different .h files, but since they got so much in common I made a baseclass and let them inherit from that and that´s when the problems started. I´ve tried to forward declare too but then I just get "class CGeneralManager has incomplete type" errors and such. Blah, I´ll just put them all into a single file! And those other defines really aren´t relevant here, it´s just some typedefs and enumerations so I can do for example
if (m_fire == FIRE_LASER)
{
// fire lasershot
}
and such.
when I said '' strip them down to a bare minimum to still get the error'' it was so that you would do most of the hard work instead of dumping a load of files on us, and then we could point out the error you''re making. As it is I don''t have time to start looking through all that.
Yep: the code that was posted is missing out important bits and still contains some errors. Fix that, reduce it down to a smaller example, and maybe we can help.

This topic is closed to new replies.

Advertisement