2

I am making a small game.

In BattleRecord.h:

#ifndef _CHARACTER_H_
#define _CHARACTER_H_
#include "Character.h"
#endif

class BattleRecord
{
public:
    Character Attacker;
    Character Defender;
    Status status;
    int DamageDealt;    
    int GoldEarned;
    int ExpGained;
};

In Character.h:

#ifndef _EQUIPMENT_H_
#define _EQUIPMENT_H_
#include "Equipment.h"
#endif

class BattleRecord;
class Character
{
BattleRecord AttackEnemy(Character &Enemy);
}

In BattleRecord.h:

#ifndef _CHARACTER_H_
#define _CHARACTEr_H_
#include "Character.h"
#endif

#ifndef _BATLE_RECORD_H_
#define _BATLE_RECORD_H_
#include "BattleRecord.h"
#endif

class GUI
{
public:
//GUI Methods, and two of these:
void ViewStats(Character &Player);
void Report(BattleRecord Record)
}

The problem here is, my Character.h and BattleRecord.h need to include each other, and this definitely will cause multiple redefinition problem. Therefore, I used forward declaration in Character.h by adding:

class BattleRecord;

The problem is sovled. But then, the GUI.h needs BattleRecord.h again for reporting the battle, so I have to include BattleRecord.h into the GUI.h. I also have to include the Character.h in order to pass into the ViewStat function. I got error and stuck with this up to this piont.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Amumu
  • 17,924
  • 31
  • 84
  • 131

5 Answers5

12

You're using inclusion guards wrong. They should appear in the file that you intend to prevent multiple inclusions only, and they should cover the entire file. (not just the includes).

For example, in BattleRecord.h

#ifndef _BATTLE_H_
#define _BATTLE_H_
#include "Character.h"

class BattleRecord
{
public:
    Character Attacker;
    Character Defender;
    Status status;
    int DamageDealt;    
    int GoldEarned;
     int ExpGained;
};

#endif // _BATTLE_H_
Mark H
  • 13,797
  • 4
  • 31
  • 45
3

Put your #endif at the end of the file not the end of your includes or use #pragma once at the top if your compiler supports this although that is less portable.

Edit:

To further explain what #ifdef & ifndef does is tell the compiler to include or exclude code entirely from compilation.

// if _UNQIUEHEADERNAME_H_ is NOT defined include and compile this code up to #endif
#ifndef _UNQIUEHEADERNAME_H_
// preprocessor define so next time we include this file it is defined and we skip it
#define _UNQIUEHEADERNAME_H_
// put all the code classes and what not that should only be included once here
#endif // close the statement 

The reason you want to do this is because including a header file is basically saying "put all the code in this file here" if you did that multiple times then you'd have naming conflicts from redefining objects and slow compile times in the best scenario.

AJG85
  • 15,849
  • 13
  • 42
  • 50
  • Pedantic note: it's the preprocessor that has to support it, not the compiler ;) – 0xC0000022L Feb 24 '11 at 15:33
  • Ah yeah i put #pragma once in every file and it works now. Thanks. However, I'm gonna change my style for defining header files by putting endif at the end. – Amumu Feb 24 '11 at 15:41
  • @STATUS Haha yes that is more correct but I didn't want to explain compilation steps as a forward preface since I suspect the OP is relatively new :P – AJG85 Feb 24 '11 at 15:46
  • @Amumu it's an either or thing usually. Most people prefer using the `#ifndef` method as it's more widely supported. Here's a brief comparison of the two methods: http://www.cplusplus.com/forum/beginner/7877/ – AJG85 Feb 24 '11 at 15:48
1

In general, use forward declaration instead of includes. This minimizes how many includes you include file contains. The only exception is when the class you are defining is a derived class, then you need to include the base class.

Lou
  • 1,955
  • 14
  • 16
  • That's not the only exception. You also need to include if you are defining a class that has an object of another class(not a pointer or reference to it). – Benjamin Lindley Feb 24 '11 at 16:08
0

In addition to the include guard issues mentioned above (you also have a _CHARACTEr_H_/_CHARACTER_H_ mismatch that might cause you trouble on line 2 of GUI.h), you may want to revise your object design so that the Character does not AttackEnemy(), but rather there is a Battle() class where two Characters are referenced and a BattleRecord is produced after the battle. This would prevent the Character class from ever having to know about BattleRecords in the first place, would allow for the possibility of multi-Character battles in the future, having multi-turn battles, or having special battles through inheritance of the Battle class.

gpcz
  • 806
  • 6
  • 8
  • Well, that's the way I intended to do in the first place, by having another class to handle the battle. However, I want to try the multiple inclusion problem. I will rewrite the header inclusion and continue to ask if there's any further problems. – Amumu Feb 24 '11 at 15:56
  • In my experience, I find that most class-related multiple inclusion problems I run into are symptoms of an OO design that could use some refactoring. – gpcz Feb 24 '11 at 16:00
0

OK everyone,

Thanks for helping me. I have rewritten all the inclusions for the header files as suggested, and it works flawless now. Take quite time a bit of time since I did it wrong for many classes.

Amumu
  • 17,924
  • 31
  • 84
  • 131