It looks like you are instantiating your class in the header file. If you do this...all files which include battle.h will also instantiate your class. This results in multiple definitions.
Do not for any reason instantiate structs or classes in your headers if you plan on multiple files using them.
If you need to instantiate a struct in your code, do it in the source module not in its header. This way you simply have object declarations in your header instead of object definitions.
This will solve your problem.
Code:
#include "Battle.h" //do not include .cpp files, only .h
//These objects are global - defined once
cTheo theo(19, 10, "Theo");
cTheo allah(20, 15, "Allah");
int main()
{
bool partyIsAlive = Battle(theo,allah);
if (partyIsAlive)
{
cout << victory;
} else cout << defeat;
return 0;
}
<Battle.h>
Code:
#ifndef BATTLE_HEADER
#define BATTLE_HEADER
#include <iostream>
#include <cstdlib>
#include <string>
#include <ctime>
using namespace std;
//Having all public variables in this class defeats the purpose of encapsulation
//Make member variables private or protected and create accessor functions
class cTheo {
protected:
int hitPoints;
int strength;
string name;
bool alive;
public:
//Constructor
cTheo(int h, int s, string n):hitpoints(h),strength(s),name(n) {}
//Are we living or dead?
bool IsAlive(void) {return alive;};
//Kill us
void Kill(void) {alive=false;};
//Return hitpoints
int GetHitPoints(void) {return hitPoints;};
//Wound us
void Injure(int injure_value)
{
hitPoints-=injure_value;
if (hitPoints<=0) Kill(); //or alive=0,Kill() does same thing
}
//Return our name
string GetName(void) {return name;};
};
//Function Prototypes
void Choice(cTheo);
void Action(cTheo, cTheo);
void Battle(cTheo Theo, cTheo Allah);
//Globals and Constants
const string victory = "Party has Survived!\n";
const string defeat = "Party has been Defeated!\n";
char choice;
//Syntax cTheo -name- (hitPoints, strength, name)
//These object cannot be instantiated here if you are doing multiple
//includes of this file - even if not, you should not instantiate here
//You do not need to since you are requiring objects to be passed as params to your
//functions...thereby showing that the programmer must instantiate a valid object
//prior to using the Action() and Choice() functions.
//cTheo theo(19, 10, "Theo");
//cTheo allah(20, 15, "Allah");
bool Battle(cTheo Theo, cTheo Allah)
{
//I would like to implement some mechanism that takes speed into account
while (Theo.IsAlive() && Allah.IsAlive())
{
//Theo goes first
Choice(Theo);
Action(Theo, Allah);
//Followed by Allah
Choice(Allah);
Action(Allah, Theo);
//If I lose in my epic and blasphemous battle...
if (Theo.IsAlive() = false)
{
Theo.Kill();
return(false);
} else return(true);
}
}
//X is the attacker
//Do not use X as a parameter name....someone will look at the code and say....
//what the heck is X?
//Name it something that relates to the object
void Choice(cTheo x)
{
cout << x.GetName() << "'s turn" << endl;
do
{
cout << "Attack (A) Defend (D) ";
cin >> choice;
} while((choice != 'A') && (choice != 'D') && (choice != 'a') && (choice != 'd'));
//I need to fix this do-while statement.
}
//X is the attacker, Y is the receiver
//Again using x and y here is very confusing
//Perhaps attacker and defender would be better or something
void Action(cTheo x, cTheo y)
{
srand(time(NULL));
int i = rand();
//Switch used b/c I want to a more options eventually
switch (choice)
{
case ('A'):
case ('a'):
cout << x.GetName() << " is attacking. \n";
y.Injure(i + 3);
break;
case ('D'):
case ('d'):
cout << x.GetName() << " is defending. \n";
cout << "On a later date, this will actually do something!\n";
break;
}
}
#endif //end of Battle.h
Commendable effort my friend. Good job.
Some tips:
Your variable naming conventions leave something to be desired.
Having a class called CTheo and an object called Theo are a bit misleading.
Perhaps you should call the class CDeity or CBaseDeity. With the example I've given you it will be easy to derive sub-Deities or different types of deities from CTheo (but I'd rename it).
EDIT: I thought about something while I was at work. Since this file will is guaranteed to only be included one time, then your object(s) will not be created more than once. However, since when you include this file in another module it is really ignored if BATTLE_HEADER evaluates to true then the only module that will know about and be able to use your objects is the first one that uses this file as a header. Also your objects will only have module scope. In other words only the module that uses this header the first time will be able to access the objects. To all other modules these objects will not exist. This is why I do not instantiate inside of headers if I can help it. There are situations where this is helpful, but this is not one of them.