Thread: Help with VC++ 6.0 (or my code) error

  1. #1
    Registered User
    Join Date
    Jul 2004
    Posts
    5

    Help with VC++ 6.0 (or my code) error

    *I'm not exactly sure if this is the right place for this*

    Hello, I'm new here. I'm teaching myself c++ and I decided to make a simple text RPG. I'm coding a "battle engine" first and I created two instances of the class cTheo to test it. It compiles with no problems, but when I run it, this is what I get:

    Code:
    Linking...
    Cpp1.obj : error LNK2005: "void __cdecl Choice(class cTheo)" (?Choice@@YAXVcTheo@@@Z) already defined in Battle.obj
    Cpp1.obj : error LNK2005: "void __cdecl Action(class cTheo,class cTheo)" (?Action@@YAXVcTheo@@0@Z) already defined in Battle.obj
    Cpp1.obj : error LNK2005: "char choice" (?choice@@3DA) already defined in Battle.obj
    Cpp1.obj : error LNK2005: "class cTheo theo" (?theo@@3VcTheo@@A) already defined in Battle.obj
    Cpp1.obj : error LNK2005: "class cTheo allah" (?allah@@3VcTheo@@A) already defined in Battle.obj
    Debug/Cpp1.exe : fatal error LNK1169: one or more multiply defined symbols found
    Error executing link.exe.
    This is the code. If it helps, I'm using VStudio 6.0 on WinXP Pro on a 533 Celeron.

    Code:
    <main>
    #include "Battle.cpp"
    
    
    int main() {
    
    	bool partyIsAlive = true;
    
    	Battle(partyIsAlive);
    
    	if (partyIsAlive == true)
    		cout << victory;
    	else
    		cout << defeat;
    
    	return 0;
    
    }
    
    <Battle.cpp>
    
    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include <ctime>
    using namespace std;
    
    class cTheo {
    public:
    	int hitPoints, strength;
    	string name;
    
    	cTheo::cTheo(int h, int s, string n)
    	{
    		cTheo::hitPoints = h;
    		cTheo::strength = s;
    		cTheo::name = n;
    	}
    
    }; 
    
    //Function Prototypes
    void Choice(cTheo);
    void Action(cTheo, cTheo);
    
    //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)
    	cTheo theo(19, 10, "Theo");
    	cTheo allah(20, 15, "Allah");
    
    bool Battle(bool& survived) {
    
    	survived = true;
    	
    	//I would like to implement some mechanism that takes speed into account
    
    	while (theo.hitPoints > 0 && allah.hitPoints > 0) {
    		//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.hitPoints = 0)
    			survived = false;
    	}
    
    	return (survived);
    }
    
    //X is the attacker
    void Choice(cTheo x) {
    
    	cout << x.name << "'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
    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.name << " is attacking. \n";
    		y.hitPoints -= i + 3;
    		break;
    	case ('D'):
    	case ('d'):
    		cout << x.name << " is defending. \n";
    		cout << "On a later date, this will actually do something!\n";
    		break;
    	}
    
    }
    Any help would be greatly appreciated.

    P.S. Please don't be offended by my use of Allah. It's not malicious -- I would just as quickly use Jesus/Bob/Jebus/Buddha/etc.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > #include "Battle.cpp"
    Yeah, this should be
    #include "Battle.h"

    Otherwise, you have two copies of everything when you compile both main.cpp and battle.cpp
    That's the "already defined in Battle.obj" bit of the error messages

    Since you don't seem to have a battle.h, make one by moving your class and function prototypes to battle.h
    Then
    #include "battle.h"
    in battle.cpp and main.cpp
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jul 2004
    Posts
    5
    Thanks, I'm gonna try it now.

  4. #4
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    I might be a camal jockey, but I'm just wondering. Does your class declaration mean:
    class Theo (as in a name)
    or
    class The o (as in O meaning object)

    I could see how it could be theo, but it seems kind of silly to name a player class after a single name. I can also see it as the latter, in which case you should upercase the O
    just a random thought.
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

  5. #5
    Registered User
    Join Date
    Jul 2004
    Posts
    5
    Okay, that did not work so I integrated the origional battle function into main and I added the other two functions to same file. Then I removed the "Battle.cpp" file from the project and ran just the main file. This seemed to fix the problem. Does anyone know why?

    Code:
    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include <ctime>
    using namespace std;
    
    class cTheo {
    public:
    	int hitPoints, strength;
    	string name;
    
    	cTheo::cTheo(int h, int s, string n)
    	{
    		cTheo::hitPoints = h;
    		cTheo::strength = s;
    		cTheo::name = n;
    	}
    
    }; 
    
    //Function Prototypes
    void Choice(cTheo);
    void Action(cTheo, cTheo);
    
    //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)
    	cTheo theo(19, 10, "Theo");
    	cTheo allah(20, 15, "Allah");
    
    int main() {
    
    	bool partyIsAlive = true;
    
    	while (theo.hitPoints > 0 && allah.hitPoints > 0) {
    		//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.hitPoints = 0)
    			partyIsAlive = false;
    	}
    
    
    	if (partyIsAlive == true)
    		cout << victory;
    	else
    		cout << defeat;
    
                    cin.get(); cin.get();
    
    	return 0;
    
    }
    
    //X is the attacker
    void Choice(cTheo x) {
    
    	cout << x.name << "'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
    void Action(cTheo x, cTheo y) {
    
    	srand(time(NULL));
    	int i = rand();
    
                    //I'm using switch because I would like to add more options eventually
    	switch (choice) {
    	case ('A'):
    	case ('a'):
    		cout << x.name << " is attacking. \n";
    		y.hitPoints -= i + 3;
    		break;
    	case ('D'):
    	case ('d'):
    		cout << x.name << " is defending. \n";
    		cout << "On a later date, this will actually do something!\n";
    		break;
    	}
    
    }

  6. #6
    Registered User
    Join Date
    Jul 2004
    Posts
    5
    Quote Originally Posted by dbgt goten
    I might be a camal jockey, but I'm just wondering. Does your class declaration mean:
    class Theo (as in a name)
    or
    class The o (as in O meaning object)

    I could see how it could be theo, but it seems kind of silly to name a player class after a single name. I can also see it as the latter, in which case you should upercase the O
    just a random thought.
    No, it's class Theo (my name).
    I just gave the class a generic, mnemonic name until I successfully created the game. This is just an experiment - I'm not gonna torture someone by forcing them to play this crap.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    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.
    Last edited by VirtualAce; 07-05-2004 at 11:44 PM.

  8. #8
    Registered User
    Join Date
    Jul 2004
    Posts
    5
    Thanks for the help You're right, I should not have named it cTheo. If I planned on doing this for more than the experience then I would've given it a better name.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  2. file reading
    By gunghomiller in forum C++ Programming
    Replies: 9
    Last Post: 08-07-2007, 10:55 PM
  3. more then 100errors in header
    By hallo007 in forum Windows Programming
    Replies: 20
    Last Post: 05-13-2007, 08:26 AM
  4. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  5. using c++ in c code
    By hannibar in forum C Programming
    Replies: 17
    Last Post: 10-28-2005, 09:09 PM