I've a project in C++ with 2 classes.
MAIN.CPP:
#include <iostream>
#include <conio.h>
#include "Player.h"
#include "Enemy.h"
using namespace std;
int main()
{
const int startHealth = 100, startArmor = 50, startEnemyHealth = 70, startWeapon = 1;
Player *Mick = new Player(startHealth, startArmor, startWeapon);
Enemy *Mon = new Enemy(startEnemyHealth);
cout << "START!" << endl;
cout << Mick->Health << " : " << Mick->Armor << endl;
cout << "ENEMY ATTACKS!" << endl;
Mon->Attack(Mick);
cout << "DAMAGE TAKEN!" << endl;
cout << Mick->Health << " : " << Mick->Armor << endl;
cout << "YOU ATTACK!" << endl;
Mick->Attack(Mon);
cout << "ENEMY'S HEALTH!" << endl;
cout << Mon->Health << endl;
_getch();
return 0;
}
PLAYER.H
#pragma once
#include "Enemy.h"
class Player
{
public:
int Health, Armor;
int Weapon;
public:
Player(const int _startHealth, const int _startArmor, const int _startWeapon);
~Player();
void Attack(Enemy *_attackedEnemy);
};
ENEMY.H
#pragma once
#include "Player.h"
class Enemy
{
public:
float Speed;
int Damage;
int Health;
public:
Enemy(const int _startEnemyHealth);
~Enemy();
void Attack(Player *_attackedPlayer);
void Refresh(Enemy *_enemyToRefresh);
};
The errors that I get are these ones:
Meanwhile, these are the errors that CodeBlocks gives me:
Can someone help me with this issue?
The problem is that your Player class refers to your Enemy class, which also refers to your Player class:
class Enemy
{
void Attack(Player *_attackedPlayer);
}
class Player
{
void Attack(Enemy *_attackedEnemy);
}
What you need is forward declaration, to inform the compiler that a particular class exists, without telling it any information about this class.
Here you can add the following line in the file Enemy.h, before the definition of the Enemy class:
class Player;
Look at this question to see what you can or cannot do with forward declarations.
Why you need it here, even with the relevant #include directives
An #include directive is basically an instruction for the preprocessor that tells it to replace the directive by the included file. The #pragma once directive ensures that the file won't be included more than once for each translation unit.
In Main.cpp, here's what is going on:
#include "Player.h": the file Player.h is included.
The first line of Player.h is #include "Enemy.h": the file Enemy.h is included.
The first line of Enemy.h is #include "Player.h": since the file Player.h has already been included, the directive is ignored.
Definition of Enemy
Definition of Player
Definition of the main function
As you can see, even with the includes, at the time of the definition of the class Enemy, the compiler doesn't know that a class Player exists yet. This is the reason why you absolutely need a forward declaration here.
Related
I'm new at C++ and I have to create a simple video game, that has an enemy class, the problem comes when I try to separate the enemy code from the main.cpp, creating enemy.h and enemy.cpp, I followed all instructions I saw on the internet but it keeps showing me the error message I hope you guys can help me.
enemy.cpp file
#include "enemy.h"
enemy::enemy(int _hp, int _attackValue, string _name) {
hp = _hp;
attackValue = _attackValue;
name = _name;
}
void enemy::attack(enemy agressor, enemy objective) {
objective.set_hp(objective.hp - agressor.attackValue);
objective.showinfo(objective, 2);
}
void enemy::showinfo(enemy enemy, int hero) {
if (hero == 1) {
cout << " \n\n\n\n\n\n\n";
cout << enemy.name;
cout << " \n\n\n\n\n\n\n\n";
for (int i = enemy.hp / 5; i > 0; i--) {
cout << "|";
}
cout << " \n\n\n\n\n\n\n\n\n";
cout << enemy.hp;
}
else {
cout << " \n\n\n\n\n\n\n";
cout << enemy.name;
cout << " \n\n\n\n\n\n\n\n";
for (int i = enemy.hp / 5; i > 0; i--) {
cout << "|";
}
cout << " \n\n\n\n\n\n\n\n\n";
cout << enemy.hp;
}
}
int enemy::get_hp() {
return hp;
}
void enemy::set_hp(int _hp) {
hp = _hp;
}
int enemy::get_attackValue() {
return attackValue;
}
string enemy::get_name() {
return name;
}
enemy.h file
#pragma once
#ifndef enemy_H
#define enemy_H
class enemy {
private:
int hp, attackValue;
string name;
public:
enemy();
enemy(int, int, string);
void attack(enemy, enemy);
void showinfo(enemy, int);
int get_hp();
void set_hp(int hp);
int get_attackValue();
string get_name();
};
#endif // !enemy_H
PD: I still don't know how to implement setcursorposition in c++ as you can see.
You have declared enemy() but haven't defined it. If you declare the default constructor, make sure you define it (possibly in your .cpp file)
That error that you get means that you violated ODR (one definition rule). In other words, when you tried to separate your enemy class from your main you didn't remote all the parts from there and ended up with the same code in multiple cpp files.
As a side note, looks like you forgot to define your enemy::enemy() constructor, or forgot to move it from main.cpp to enemy.cpp?
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I have a class Player and a class Team.
I want to create a vector of Players in constructor of class Team. I have written a method called fillVector witch creates all the players. I have added method fillVector into class Team witch is shown bellow. I do not think class Player is necessary.
When I compile my programm with codeblocks there is the following error:
Team.cpp|9|undefined reference to `Team::fillTeamVector(std::vector >&)'|
|error: ld returned 1 exit status|
This is the Team.cpp code :
#include "Team.h"
#include <vector>
#include <iostream>
#include "Player.h"
Team::Team()
{
vector<Player> team;
fillTeamVector(team);
}
void fillTeamVector(vector<Player>& team){
cout << "How many players are in the team? " <<endl;
string name;
int teamSize,x,y,num,target_line;
cin >> teamSize;
for (int i=0 ; i<=teamSize ; i++){
cout << "Give player's name" << endl;
cin >> name;
cout << "Give player's number" << endl;
cin >> num;
cout << "Give player's x position" << endl;
cin >> x;
cout << "Give player's y position" << endl;
cin >> y;
cout << "Give player's target line" << endl;
cin >> target_line;
Player newPlayer(name,num,x,y,target_line);
team.push_back(newPlayer);
}
}
This is the Team.h code :
#ifndef TEAM_H
#define TEAM_H
#include <iostream>
#include <vector>
#include "Player.h"
using namespace std;
class Team
{
public:
Team();
void fillTeamVector(vector<Player>&);
};
#endif // TEAM_H
This is the main.cpp code :
#include <iostream>
#include <stdio.h>
#include "Player.h"
#include "Team.h"
using namespace std;
int main()
{
Team team;
return 0;
}
You have defined "fillTeamVector" as a free function in team.cpp, while it's a member function in the .h.
So fillTeamVector method of Team does not exist, but is called, hence the error.
In team.cpp, replace this :
void fillTeamVector(vector& team)
by this :
void Team::fillTeamVector(vector& team)
You've declared the function:
void fillTeamVector(vector<Player>& team){ // ...
But you forgot the "class-scope", that because that function is a member-function so you have to add:
void Team::fillTeamVector(vector<Player>& team){ // ...
Exactly what you've done for the constructor (Team::Team()).
You wrote a function called fillTeamVector.
This is not the same thing as a class method called Team::fillTeamVector, which is called by the constructor.
I'm attempting to practice some coding in my free time (combining a number of different interests of mine to help keep myself engaged) and I've encountered a odd error that I can't find the answer to. I have 4 files that I'm working with, two header files, one class definition file and a main file. I'm fairly confident I'm not including the Dice.h file more then once (however that is where the error points to and I'm not sure anymore, hence this question). What have I bungled here to produce these errors?
The error codes
Error 3 error LNK1169: one or more multiply defined symbols found (file path trimmed)
Error 2 error LNK2005: "int __cdecl dice(int,int)" (?dice##YAHHH#Z) already defined in Creature.obj (file path trimmed)
The filepath: c:\Users\Username\documents\visual studio2010\Projects\RPGTest\RPGTest\RPGTest.(error 3 referenced a .exe file, error 2 referenced a .obj file).
The code itself:
Dice.h
#ifndef SET_DICE_H_
#define SET_DICE_H_
#include <iomanip>
#include <iostream>
#include <stdlib.h>
using namespace std;
int dice(int number, int sides){
int total=0, dice;
srand(time(NULL));
int results=0;
do {
dice = rand()%sides+1;
total+=dice;
number--;
} while (number > 0);
results = total;
return results;
}
#endif
Creature.h
#ifndef CREATURE_H_
#define CREATURE_H_
#include <iomanip>
#include <iostream>
#include "Dice.h"
using namespace std;
class Creature {
public:
Creature(int,int,int,int,int,int,int,int,int,int,int,int);
void set_hp();
void set_saves();
void set_ac();
void set_bab();
void set_name();
void update_hp(int);
void update_ac(int);
void update_fsave(int);
void update_rsave(int);
void update_wsave(int);
int get_ac();
int get_hp();
int get_fsave();
int get_rsave();
int get_wsave();
int get_bonus(int);
int get_bab();
string get_name();
private:
int strength, dexterity, constitution, intellegence, wisdom, charisma;
int bab, fbsave, rbsave, wbsave;
int hdnum, hdsize;
int hp, fsave, rsave, wsave, ac;
string name;
};
#endif
Creature.cpp
#include "Creature.h"
#include <math.h>
#include <iostream>
using namespace std;
Creature::Creature(int strength,int dexterity,int constitution,
int intellegence,int wisdom,int charisma,int bab,int fbsave,
int rbsave,int wbsave,int hdnum,int hdsize){
strength = strength;
dexterity = dexterity;
constitution = constitution;
intellegence = intellegence;
wisdom = wisdom;
charisma = charisma;
bab = bab;
fbsave = fbsave;
rbsave = rbsave;
wbsave = wbsave;
hdnum = hdnum;
hdsize = hdsize;
}
int Creature::get_bonus(int stat){
int bonus = floor((double(stat)-10)/2);
return bonus;
}
void Creature::set_ac(){
ac=10+get_bonus(dexterity);
}
void Creature::set_hp(){
hp = dice(hdnum,hdsize) + get_bonus(constitution)*hdnum;
}
void Creature::set_saves(){
fsave = fbsave + get_bonus(constitution);
rsave = rbsave + get_bonus(dexterity);
wsave = wbsave + get_bonus(wisdom);
}
void Creature::set_bab(){
bab = hdnum;
}
void Creature::set_name(){
cout << "Please enter a name for this creature: ";
cout << "\nSorry! I don't work yet!";
cout << "\nInstead all creatures are named Larry!\n";
name = "Larry!";
}
void Creature::update_hp(int input){
hp = hp + input;
}
void Creature::update_fsave(int input){
fsave = fsave+input;
}
void Creature::update_rsave(int input){
rsave = rsave+input;
}
void Creature::update_wsave(int input){
wsave = wsave+input;
}
void Creature::update_ac(int input){
ac = ac+input;
}
int Creature::get_ac(){
return ac;
}
int Creature::get_hp(){
return hp;
}
int Creature::get_fsave(){
return fsave;
}
int Creature::get_rsave(){
return rsave;
}
int Creature::get_wsave(){
return wsave;
}
int Creature::get_bab(){
return bab;
}
RPGTest.cpp
#include "Creature.h"
#include <math.h>
//#include "Dice.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int str = dice(3,6), dex = dice(3,6), con = dice(3,6), intel = dice(3,6), wis = dice(3,6), cha = dice(3,6);
int fbs = dice(1,6), rbs = dice(1,6), wbs = dice(1,6);
int hdn = dice(1,10), hds = 8, bab = dice(1,8);
cout << "Welcome to RPG Creature Tester v0.1\n";
cout << "This .exe file is meant to test the creature class functions and definitions.\n";
cout << "This will be done by randomly generating and displaying a creature.\n";
cout << "What you don't see right now is the random generation of a creature.\n";
cout << "Once it's finished, the \'statsheet\' will be shown.\n";
cout << "Cheers!\n\n";
Creature potato (str, dex, con, intel, wis, cha, bab, fbs, rbs, wbs, hdn, hds);
potato.set_ac();
potato.set_hp();
potato.set_name();
potato.set_saves();
cout << "OUTPUT BRICK YAY\n";
cout << "Str: " << str << endl;
cout << "HP: " << potato.get_hp() << " AC: " << potato.get_ac() << " Fort/Reflex/Will Save: " << potato.get_fsave() << "/" << potato.get_rsave() << "/" << potato.get_wsave();
return 0;
}
Since I'm mainly self-taught I'm happy for any other advice but my main issue is that I'm not sure why I'm getting the "multiple" definition error. I did some research into other questions with similar error messages but I didn't see anything that immediately jumped out at me as "the answer".
Thanks all!
C++ works by compiling single translation units and then linking them together.
This means that each source file gets compiled on its own. Since the #include directive basically inserts all the code included, in your situation you end up having multiple translation units which define
int dice(int number, int sides) {
...
}
Compilation goes through fine but, when linking, multiple definition of this function are found so this generates the error.
To solve this problem you have two ways:
declare int dice(int, int) in a header file but define (implement it) in a source file
keep the definition as it is but prepend static to it. This tells the compiler that each translation unit will get its own dice method. This solution, although tempting, leads to binary size increase since you will have multiple implementation of the same method
So I have some code in couple of files:
cells.cpp:
#include "cells.h"
#include <iostream>
using namespace std;
char convertIntChar (int symbolNumber)
{
char charR;
switch (symbolNumber)
{
case 0:
charR='0';
break;
// lust of case code here
case 63:
charR='\\';
break;
}
return charR;
}
class cell
{
public:
int iPosition;
char chPosition;
cell ()
{
static int i = -1;
i++;
chPosition=convertIntChar (i);
iPosition=i;
cout << " " << iPosition; //two lines of code to test
cout << " " << chPosition; //constructor
}
protected:
};
main.cpp
#include <iostream>
#include "cells.h"
#include "pointer.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
createPointer();
cell cells[64];
return 0;
}
And comeplytly a cells.h
#ifndef CELLS_H_INCLUDED
#define CELLS_H_INCLUDED
#pragma once
class cell
char convertIntChar(int symbolNumber);
#endif // CELLS_H_INCLUDED
There I have an erros that sounds like
//filepath\|5|error: two or more data types in declaration of 'convertIntChar'|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 7 seconds) ===|
What can it be. Sorry for noob question anyway.
First, this forward declaration needs a semi-colon:
class cell;
// ^
Second, you cannot use a forward declaration here. main.cpp needs to see the cell class definition. So you should put the definition in cells.h. For example:
cells.h:
#ifndef CELLS_H_INCLUDED
#define CELLS_H_INCLUDED
class cell
{
public:
int iPosition;
char chPosition;
cell ();
};
char convertIntChar(int symbolNumber);
#endif
cells.cpp:
#include "cells.h"
#include <iostream>
char convertIntChar (int symbolNumber)
{
char charR;
// as before
return charR;
}
cell::cell ()
{
static int i = -1;
i++;
chPosition=convertIntChar (i);
iPosition=i;
std::cout << " " << iPosition; //two lines of code to test
std::cout << " " << chPosition; //constructor
}
You have class cell in the cpp file which should go into the .h file.
Then in cells.h you are missing a ; after class cell.
Insterad of the forward declaration in cell.h, put the class there.
I have copied this out of a book. I'm just not sure what to add in the main.cpp source file to make it run though.
I know that class declarations go in the .h file and implementations go in the .cpp file. What would I need to write in main.cpp?
I've tried lots of different things but I'm just getting so many error messages.
// cat.h
#ifndef ____2_cat_implementation__Cat__
#define ____2_cat_implementation__Cat__
#include <iostream>
using namespace std;
class Cat
{
public:
Cat (int initialAge);
~Cat();
int GetAge() { return itsAge;}
void SetAge (int age) { itsAge = age;}
void Meow() { cout << "Meow.\n";}
private: int itsAge;
};
#endif /* defined(____2_cat_implementation__Cat__) */
...
// cat.cpp
#include <iostream>
#include "Cat.h"
using namespace std;
Cat::Cat(int initialAge)
{
itsAge = initialAge;
}
Cat::~Cat()
{
}
int main()
{
Cat Frisky(5);
Frisky.Meow();
cout << "Frisky is a cat who is ";
cout << Frisky.GetAge() << " years old.\n";
Frisky.Meow();
Frisky.SetAge(7);
cout << "Now Frisky is " ;
cout << Frisky.GetAge() << " years old.\n";
return 0;
}
Look at this part again:
Cat::Cat(int initialAge);
{
itsAge = initialAge;
Cat::~Cat()
You're missing the closing } for the constructor, as well as an extra ; after the function header.
On an unrelated note, don't use global names starting with underscore (like ____2_cat_implementation__Cat__), those names a reserved by the specification.
You have a missing } and unneccessary ;
//----------------------v
Cat::Cat(int initialAge);
{
itsAge = initialAge;
}
//^
What would I need to write in main.cpp
Usially, as you have pointed out, the .h file contains the declarations and the .cpp file - the definitions. Then, the main.cpp file should contain the main function (it's not necessary to name the file, containing the main function main.cpp. It could be anything.
So, in your example, you can create a main.cpp file with the following content:
// include the declarations file
#include "cat.h"
// include the header for cin/cout/etc
#include <iostream>
using namespace std;
int main()
{
Cat Frisky(5);
Frisky.Meow();
cout << "Frisky is a cat who is ";
cout << Frisky.GetAge() << " years old.\n";
Frisky.Meow();
Frisky.SetAge(7);
cout << "Now Frisky is " ;
cout << Frisky.GetAge() << " years old.\n";
return 0;
}
Other notes:
using namespace std; is bad practice, especially in header files. Use std:: instead (for example, std::cout, std::cin, std::string, etc)
as you have .h and .cpp files, don't put half of the implementation in the header and the rest - in the source file. Put all definitions inside the source files (unless you want to inline the functions, implemented in the header)
avoid using names, starting with __ or _ - they are reserved by the standard.