0
votes

my friend and I are learning C++ together and we have a question. We have created a header file that contains a class which uses static variables and static functions, these functions and variables need to be accessible to a total of 2+ .cpp files but because we are initializing the static variables in the header the header file can only be read one time (due to static the variable initializations).

We have tried only including the header file in our MainFunction.cpp file but the other .cpp files have no ability to use the static variables and functions if we do this. Including the header file in (currently) both .cpp files that require the functions/variables results in a wide array of link errors due to the static variables being initialized multiple times.

Here is the Header File which contains the class and the static variable initialization:

//PlayerStatistics.h
// Classes
class PlayerStatistics
{
public:
    // Functions To Change Player Statistics
    static void SetStats(short int HitPoints, short int MagickaPoints, short int Fatigue, short int Damage, short int Defense, short int Dodge, short int Block, short int SpellCastChance);
    static void SetLevel(short int Experience, short int Level);
    static void SetExperience(short int Experience);

    // Player Statistics
    static short int HitPoints;
    static short int MagickaPoints;
    static short int Fatigue;
    static short int Damage;
    static short int Defense;

    // Chance Based System Player Statistics (Relies on Fatigue Level)
    static short int Dodge;
    static short int Block;
    static short int SpellCastChance;

    static short int Experience;
    static short int Level;
};

// STATIC VARIABLES
short int PlayerStatistics::HitPoints = 20;
short int PlayerStatistics::MagickaPoints = 20;
short int PlayerStatistics::Fatigue = 20;
short int PlayerStatistics::Damage = 20;
short int PlayerStatistics::Defense = 20;
short int PlayerStatistics::Dodge = 20;
short int PlayerStatistics::Block = 20;
short int PlayerStatistics::SpellCastChance = 20;
short int PlayerStatistics::Experience = 0;
short int PlayerStatistics::Level = 1;

And the 2 .cpp files that require access:

1:

//PlayerCharcter.cpp
void PlayerStatistics::SetLevel(short int Experience, short int Level)
{
Experience = Experience;
Level = Level;
}

void PlayerStatistics::SetStats(short int HitPoints, short int MagickaPoints, short int Fatigue, short int Damage, short int Defense, short int Dodge, short int Block, short int SpellCastChance)
{
HitPoints = HitPoints;
MagickaPoints = MagickaPoints;
Fatigue = Fatigue;
Damage = Damage;
Defense = Defense;
Dodge = Dodge;
Block = Block;
SpellCastChance = SpellCastChance;
}

void PlayerStatistics::SetExperience(short int Experience)
{
Experience = PlayerStatistics::Experience;
}

void AddExperience()
{
// This is a Testing Function to test the Level Up system and should be removed once Creatures
// are added to the game, or it can be edited to include proper experience points given for
// killing curtain enemies.

short int GetExperienceNumber;
std::cout << "How many experience points do you want? \n";
std::cin >> GetExperienceNumber;

PlayerStatistics::Experience = (PlayerStatistics::Experience += GetExperienceNumber);
std::cout << GetExperienceNumber << " Experience Points Added! \n \n \n \n \n";
}

2:

//WordBank.cpp
        std::cout << "\n \n \n \n \n \n \n \n \n \n \n \n"
        << PlayerName << "'s Character Sheat! \n \n \n"
        << "Level: " << PlayerStatistics::Level << "\n"
        << "Experience: " << PlayerStatistics::Experience << "\n \n \n"
        << "Health: " << PlayerStatistics::HitPoints << "\n"
        << "Magicka: " << PlayerStatistics::MagickaPoints << "\n"
        << "Fatigue: " << PlayerStatistics::Fatigue << "\n"
        << "Attack: " << PlayerStatistics::Damage << "\n"
        << "Defense: " << PlayerStatistics::Defense << "\n"
        << "Dodge Skill: " << PlayerStatistics::Dodge << "\n"
        << "Block Skill: " << PlayerStatistics::Block << "\n"
        << "Spell Casting Skill: " << PlayerStatistics::SpellCastChance << "\n"
        << "\n \n \n \n \n \n \n" << "To Continue Type Any Key In And Hit Enter" << std::endl;

We need to #include this header file in these 2 .cpp files (with 2 more planned that will require access to this class as well) but only actually read the header file one time (so we can avoid reading the static variable initializations more then once). We are trying to steer clear of constructors (mainly for the ease of use with statics but also for our learning purposes). We have read about Header Guards but we can't figure out how to make them work with this problem.

Any tips/advice you have will be very much appreciated!

1
Look up "header guard" or "include guard".chris
Hmm, we are trying to figure out the inner-workings of Header Guards and such now. Thank you very much!TorbenC

1 Answers

1
votes

You should probably put only declaration of variables in your header files (and those should be extern, not static, global variables, or static member variables with external linkage). So keep having static member variables declarations like (in your PlayerStatistics.h header file)

class PlayerStatistics {
   /// ....
   static short int HitPoints;
};

(it is a static member variable declaration with external linkage)

Then you can put definitions like

short int PlayerStatistics::HitPoints = 20;
short int PlayerStatistics::MagickaPoints = 20;
short int PlayerStatistics::Fatigue = 20;

in one single implementation file (often conventionally the one containing main, e.g. some main.cpp).

You should probably put include guards in your header file, that is starting it with

#ifndef PLAYER_STATISTICS_INCLUDED
#define PLAYER_STATISTICS_INCLUDED

and ending it with

#endif /*PLAYER_STATISTICS_INCLUDED*/

I strongly suggest you to study the source code of some existing C++ free software application (e.g. from http://freecode.com/ or other free software collection). This will teach you a big lot.