How to fix error in Hero.h ?
GCC C++ compiler flags : -c -fmessage-length=0 -std=gnu++11 ;
I update g++ to 4.8.1
// Creature.h
#pragma once
#ifndef CREATURE_H_
#define CREATURE_H_
#include <string>
#include "Hero.h"
#include "Characteristics.h"
#include <map>
class Creature
{
private:
CreatureCharacteristics Characters;
Creature(const std::string i_name, int i_count = 0);
Creature(const Creature& Donor);
public:
typedef std::map < std::string, Creature* > Prototypes;
static Prototypes Clones_Bank;
~Creature();
const CreatureCharacteristics& Get_characteristics(){
return this->Characters;
}
static Creature*& Clone(std::string i_name, int i_count = 0);
};
#endif /* CREATURE_H_ */
// Hero.h
#pragma once
#ifndef HERO_H_
#define HERO_H_
#include "Creature.h"
#include "Characteristics.h"
#include <string>
#include <vector>
typedef std::vector<Creature*> Army; // ERROR HERE (‘Creature’ was not declared in this
scope)
class Hero {
private:
Army army;
HeroCharacteristics base_characteristics;
public:
Hero(std::string name = '\0', int attack = 0, int defense = 0):
hero_name(name)
{
base_characteristics.attack = attack;
base_characteristics.defence = defense;
};
const Army& Get_army() const
{
return army;
};
const std::string& Get_name() const
{
return hero_name;
};
const HeroCharacteristics& Get_characteristics() const
{
return base_characteristics;
};
void Add_creature(Creature* creature, int creature_count);
};
#endif /* HERO_H_ */
The problem is that Hero.h and Creature.h include each other: you have a cyclic dependency. When Hero.h includes Creature.h and Creature.h tries to include Hero.h again, HERO_H_ is already defined, and thus nothing gets inserted (if you removed the include guards, you would get an endless include cycle which is no good either).
However, it seems that Creature.h does not actually use Hero.h, so you can just remove this header. If you later do need something from the header, you may very well get away with a forward declaration. For more on this, see the C++ FAQ entry "How can I create two classes that both know about each other?".
Related
I have these files structure:
main.cpp
#include "main.h"
Map map;
Fruit fruit;
Stone stone;
main.h
extern Map map;
extern Fruit fruit;
extern Stone stone;
map.h
#include "main.h"
class Map {public: int size = 20;};
fruit.h
#include "main.h"
class Fruit { public: int pos = 1; draw() {return map.size;} };
stone.h
#include "main.h"
class Stone { public: draw() {return map.size * fruit.pos;} };
The problem is when I'm trying to use map.size and fruit.pos I get error:
'map': undeclared identifier
The same with stone. So, what's wrong?
main.h should include map.h not the other way around.
main.h should include fruit.h not the other way around.
main.h should include stone.h not the other way around.
Also you should add include guards to your header files.
EDIT
Here's one way that works, (I can't believe I recommending code like this but still)
// map.h
#ifndef MAP_H
#define MAP_H
class Map {public: int size = 20};
extern Map map;
#endif
// fruit.h
#ifndef FRUIT_H
#define FRUIT_H
#include "map.h"
class Fruit { public: int pos = 1; draw() {return map.size;} };
extern Fruit fruit;
#endif
// stone.h
#ifndef STONE_H
#define STONE_H
#include "map.h"
#include "fruit.h"
class Stone { public: draw() {return map.size * fruit.pos;} };
extern Stone stone;
#endif
// main.cpp
#include "map.h"
#include "fruit.h"
#include "stone.h"
Map map;
Fruit fruit;
Stone stone;
This is not how you are supposed to write code.
Files (*.h or *.cpp) should only include files that they directly depend upon.
Files should not include files that they do not depend upon.
One way to break cyclical dependencies is to put the implementation in the foo.cpp source file instead of inline in the foo.h header file.
One way to break dependencies on global variables is to instead pass them in as parameters instead of having them hard-coded into the routines.
Use of a forward declaration can be used to avoid including an header file that is only used to declare the type. Only when the details of the type, such as its methods and footprint, are not important. Alas, forward declarations for template classes are trickier.
For the files in the OP example, here's an alternative implementation incorporating those suggestions.
fruit.h
#ifndef FRUIT_H
#define FRUIT_H
class Map;
class Fruit {
public:
int pos = 1;
auto draw(Map const&) -> int;
};
#endif
map.h
#ifndef MAP_H
#define MAP_H
class Map {
public:
int size = 20;
};
#endif
stone.h
#ifndef STONE_H
#define STONE_H
class Fruit;
class Map;
class Stone {
public:
auto draw(Map const& map, Fruit const& fruit) -> int;
};
#endif
fruit.cpp
// Identity.
#include "fruit.h"
// Other dependencies.
#include "map.h"
auto Fruit::draw(Map const& map) -> int {
return map.size;
}
stone.cpp
// Identity.
#include "stone.h"
// Other dependencies.
#include "fruit.h"
#include "map.h"
auto Stone::draw(Map const& map, Fruit const& fruit) -> int {
return map.size * fruit.pos;
}
main.cpp
#include <iostream>
#include "fruit.h"
#include "map.h"
#include "stone.h"
using std::cout;
int main() {
auto map = Map{};
auto fruit = Fruit{};
auto stone = Stone{};
map.size = 17;
fruit.pos = 3;
cout << "map.size is " << map.size << "\n";
cout << "fruit.pos is " << fruit.pos << "\n";
cout << "fruit.draw(map) is " << fruit.draw(map) << "\n";
cout << "stone.draw(map, fruit) is " << stone.draw(map, fruit) << "\n";
}
I've looked this up and the closest thing I found was this except I don't have any forward declarations. I only have one pure virtual function in the base class which I'm implementing in the subclass as follows:
Command.h
#ifndef _COMMAND_H_
#define _COMMAND_H_
#include <string>
#include "Stack.h"
#include "Number.h"
class Command
{
public:
std::string cmdType;
Command(void);
Command (std::string cmdType);
virtual void executeCommand(Stack<Number> & stack) = 0;
~Command (void);
};
#endif // !defined _COMMAND_H_
Command.cpp
Command::Command(void)
:cmdType("")
{}
Command::Command(std::string cmdType)
:cmdType(cmdType)
{}
Command::~Command(void)
{}
Number.h
#ifndef _NUMBER_H_
#define _NUMBER_H_
#include "Command.h"
#include "Stack.h"
class Number : public Command
{
public:
Number (float num);
void executeCommand(Stack<Number> & stack);
float val;
~Number (void);
};
#endif // !defined _NUMBER_H_
Number.cpp
#include "Number.h"
Number::Number(float num)
:val(num)
{
cmdType = "hi";
}
void Number::executeCommand(Stack<Number> & stack)
{
stack.push((*this));
}
File error occurs:
Error 4 error C2259: 'Number' : cannot instantiate abstract class c:\...\add.cpp 34
Add.cpp
#include "Add.h"
Add::Add(void)
:Binary("+")
{
}
Add::~Add(void)
{
}
void Add::executeCommand(Stack<Number> & numStack)
{
Number num1 = numStack.top(); //THIS LINE HAS THE ERROR
numStack.pop();
Number num2 = numStack.top();
numStack.pop();
float tempVal = num2.val + num1.val;
num1.val = tempVal;
numStack.push(num1);
}
Add.h
#ifndef _ADD_H_
#define _ADD_H_
#include "Stack.h"
#include "Number.h"
#include "Binary.h"
class Add : public Binary
{
public:
Add (void);
void executeCommand (Stack<Number> & numStack);
~Add (void);
};
#endif // !defined _ADD_H_
This is a circular dependency problem.
Command.h includes Number.h
Number.h includes Command.h
Usually it is solved by replacing one of the includes with a forward declaration, try forward-declaring Number in Command.h instead of including Number.h; move that include to Command.cpp.
I got three .cpp files and two header files.
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Below is my Data.h(previously known as 2.h at above)
#include <iostream>
#include <string>
using namespace std;
class Data
{
private:
string sType;
public:
Data();
Data(string);
void setSType(string);
string getSType();
};
Below is my data.cpp
#include "Data.h"
Data::Data()
{
sType = "";
}
Data::Data(string s)
{
sType = s;
}
void Data::setSType(string ss)
{
sType = ss;
}
string Data::getSType()
{
return sType;
}
Below is my PointD.h (previously known as 3.h)
#include <iostream>
#include <string>
#include "Data.h"
using namespace std;
class PointD
{
private:
int x
Data data1;
public:
PointD();
PointD(int,Data);
void setX(int);
void setData(Data);
int getX();
Data getData();
};
Below is my PointD.cpp
#include "PointD.h"
PointD::PointD()
{
x = 0;
}
PointD::PointD(int xOrdinate,Data dd)
{
x = xOrdinate;
data1 = dd;
}
void PointD::setXordinate(int Xordinate)
{
x = Xordinate;
}
void PointD::setData(Data dd)
{
data1 = dd;
};
int PointD::getXordinate()
{
return x;
}
Data PointD::getData()
{
return data1;
}
This is my main.cpp
#include <iostream>
#include <string>
#include "Data.h"
#include "PointD.h"
using namespace std;
int main()
{
const int MAX_NUM = 20;
Data ldata[MAX_NUM];
PointD pointd[MAX_NUM];
//more codes..
}
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Can anybody let me know whats actually went wrong here..
You need to use include guards, or the easiest:
#pragma once
in your header files
See Purpose of Header guards for more background
Idea: 1.hpp
#ifndef HEADER_GUARD_H1_HPP__
#define HEADER_GUARD_H1_HPP__
// proceed to declare ClassOne
#endif // HEADER_GUARD_H1_HPP__
In each of your header files write:
#ifndef MYHEADERNAME_H
#define MYHEADERNAME_H
code goes here....
#endif
Its better like this:
#ifndef DATA_H /* Added */
#define DATA_H /* Added */
#include <iostream>
#include <string>
// using namespace std; /* Removed */
class Data
{
private:
std::string sType;
public:
Data();
Data( std::string const& ); // Prevent copy of string object.
void setSType( std::string& ); // Prevent copy of string object.
std::string const& getSType() const; // prevent copy on return
std::string& getSType(); // prevent copy on return
};
#endif /* DATA_H */
The big fix is adding ifndef,define,endif. The #include directive works as if copying and pasting the .h to that line. In your case the include from main.cpp are:
main.cpp
-> Data.h (1)
-> Point.h
-> Data.h (2)
At (2), Data.h has already been `pasted' into main.cpp at (1). The class declaration of Data, i.e. "class Data{ .... };" , appears twice. This is an error.
Adding include guards to the top and bottom of every .h are standard practice to avoid this problem. Don't think about it. Just do it.
Another change I'd suggest is to remove any "using namespace ..." lines from any .h . This breaks the purpose of namespaces, which is to place names into separate groups so that they are not ambiguous in cases where someone else wants an object or function with the same name. This is not an error in your program, but is an error waiting to happen.
For example, if we have:
xstring.h:
namespace xnames
{
class string
{
...
};
}
Foo.h
#include <xstring>
using namespace xnames;
...
test.cxx:
#include "Foo.h"
#include "Data.h" // Breaks at: Data( string ); -- std::string or xnames::string?
...
void test()
{
string x; // Breaks. // std::string or xnames::string?
}
Here the compiler no longer knows whether you mean xnames::string or std::string. This fails in test.cxx, which is fixable by being more specific:
void test()
{
std::string x;
}
However, this compilation still now breaks in Data.h. Therefore, if you provide that header file to someone, there will be cases when it is incompatible with their code and only fixable by changing your header files and removing the "using namespace ...;" lines.
Again, this is just good coding style. Don't think about it. Just do it.
Also, in my version of Data.h, I've changed the method parameters and return types to be references (with the &). This prevents the object and all of its state from being copied. Some clever-clogs will point our that the string class's is implementation prevents this by being copy-on-write. Maybe so, but in general, use references when passing or returning objects. It just better coding style. Get in the habit of doing it.
In Weapon.h, when I try and take a class 'Entity*' as a parameter, it says "Syntax error: identifier 'Entity'" when I compile. Additionally when I roll over the text 'target', Visual C++ Express 2010 gives me the text " *target". The Entity class is fine and I'm pretty sure it's included correctly.
(I won't post Player.h as it's unnecessary - see Library.h - but it has a header guard and includes Entity.h)
Library.h:
#ifndef _LIBRARY_
#define _LIBRARY_
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <map>
#include <exception>
#include <sstream>
//file includes
#include "Globals.h"
#include "Player.h"
#include "Exception.h"
#include "Weapon.h"
#include "Armour.h"
#include "Consumable.h"
//prototypes that require "Library.h"
bool Poglathon(std::vector<std::string>& text,Player *player);
bool PoglathonTown(std::vector<std::string>& text,Player *player);
std::map<std::string,Weapon*> init_weapons(void);
std::map<std::string,Armour*> init_armour(void);
std::map<std::string,Consumable*> init_consumables(void);
#endif //__LIBRARY__
Weapon.h:
#ifndef _WEAPON_H_
#define _WEAPON_H_
#include "Shopable.h"
class Weapon : public Shopable{
private:
int Damage;
public:
Weapon(int c,int d,std::string n) : Shopable(c,n),Damage(d){}
std::string getDesc() const{
return getName()+"\t"+tostring(Damage)+"\t"+tostring(Cost);
}
int getDamage() const{return Damage;}
int DamageTarget(Entity* target){
int DamageDealt = 0;
//do damage algorithm things here
return DamageDealt;
}
};
#endif
Shopable.h:
#ifndef _SHOPABLE_H_
#define _SHOPABLE_H_
#include "Library.h"
class Shopable{
protected:
std::string Name;
int Cost;
std::string Description;
public:
Shopable(int c, std::string n):Cost(c),Name(n){}
std::string getName() const{return Name;}
int getCost() const {return Cost;}
virtual std::string getDesc() const = 0;
};
#endif
Entity.h:
#ifndef _ENTITY_
#define _ENTITY_
#include "Library.h"
#include "Weapon.h"
#include "Armour.h"
#include "Consumable.h"
class Entity{
public:
void printStats() const;
void heal(double health);
std::string name;
protected:
//player stats
double str; //strength
double wis; //wisdom
double ref; //reflex
double hp; //health points
double maxHp; //maximum health points
double i; //initiative
double inte; //intelligence
double c; //courage
int gold; //gold
int xp; //experience
int ap; //armour points
int wd; //weapon damage
int lvl; //level
int sp; //skill points
Weapon* weapon;//weapon
Armour* cArmour;//current armour
};
#endif
In C++, classes must be declared before they are referenced. You are #include-ing Weapon.h in Entity.h, but at that point, the compiler doesn't know about the existence of class Entity.
You will either need to change the order in which things are declared, or add a forward declaration "above" class Weapon. It can simply be:
class Entity;
That tells the compiler that there is such a name as Entity. However, it doesn't tell it anything about what members it has, so you can't actually do anything with it, other than declare variables of Entity * and Entity &, and pass them around.
Your headers include each other because your classes refer to each other. (But your compiler doesn't suffer from a stackoverflow because of your include guards - that's a good thing!)
You should arrange your header files hierarchically, ie there are files at the 'top' which #include nothing and files 'below' which include some of the top ones and so-on down the hierarchy. But at no point should there be 'loops'.
In order to break your loops in your code, any classes that refer to each other should forward declare any mutual dependencies and only refer to dependency names and not their members.
e.g.
Entity.h
class Weapon;
class Entity{
...
Weapon* weapon;
};
Weapon.h
class Entity;
class Weapon{
...
int DamageTarget(Entity* target);
};
Notice how Weapon.h only refers to Entity*.
You will need to define int Weapon::DamageTarget(Entity* target) in Weapon.cpp
#include <entity.h>
Or forward-declare only in the header
class Entity;
This makes compilation a bit faster (you still need to include it to use in the implementation).
Weapon.h doesn't #include Entity.h, or anything that recursively includes it. Therefore, it doesn't know about the class Entity.
I'm pretty sure I've included the qanda class, but when I try to declare a vector that contains it or a class of that type I get an error saying that qanda is undefined. Any idea what the problem might be?
bot_manager_item.h
#pragma once
#include "../bot_packet/bot_packet.h"
#include <vector>
class bot_manager_item;
#include "qanda.h"
#include "bot_manager.h"
class bot_manager_item
{
public:
bot_manager_item(bot_manager* mngr, const char* name, const char* work_dir);
~bot_manager_item();
bool startup();
void cleanup();
void on_push_event(bot_exchange_format f);
bool disable;
private:
void apply_changes();
bot_manager *_mngr;
std::string _name;
std::string _work_dir;
std::string _message;
std::string _message_copy;
std::vector<qanda> games;
qanda test;
char _config_full_path[2600];
};
qanda.h
#ifndef Q_AND_A
#define Q_AND_A
#include "users.h"
#include "..\bot_packet\bot_packet.h"
#include "bot_manager.h"
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <fstream>
class qanda
{
public:
qanda(bot_manager * manager, std::string name, std::string directory);
~qanda(){};
void room_message(std::string username, std::string user_message);
void timer_tick();
private:
// data members
std::string question;
std::string answer;
std::string directory;
std::string command_prefix;
std::string name;
Users users;
std::map <std::string, std::string> questions_and_answers;
int time_per_question; // seconds
int time_between_questions; // seconds
int timer; // milliseconds
bool is_delayed;
bool is_playing;
bot_manager * manager;
// functions
void new_question();
void send_message(std::string msg);
void announce_question();
void load_questions();
};
#endif
Solved: I ended up refactoring the code in such a way as to avoid the use of bot_manager within the qanda class.
I suspect a circular #include problem. Is it possible qanda.h indirectly includes bot_manager_item.h?
It looks like you may be able to reduce header dependencies by using a forward declaration
class bot_manager;
instead of #include "bot_manager.h" in one or both of your posted header files.