Header file imports acting strangely [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Circular dependencies with headers. Using #ifndef and #define
I try to import a header file that contains a class that extends to class in that header file and it doesn't work :S
TileGrass.h:
#ifndef TILEGRASS_H_
#define TILEGRASS_H_
#include "Tile.h"
class TileGrass : public Tile
{
public:
TileGrass(unsigned char);
};
#endif /* TILEGRASS_H_ */
Tile.h:
#ifndef TILE_H_
#define TILE_H_
class Tile
{
public:
Tile(unsigned char);
unsigned char id;
};
#include "TileGrass.h"
extern Tile* tiles[256];
TileGrass tileGrass = TileGrass(0);
#endif /* TILE_H_ */
Doing this gives me the error:
error: 'TileGrass' does not name a type

At a first glance, I see two errors:
a circular include which isn't necessary (Tile.h doesn't need to include TileGrass.h - you can just re-organize the file to remove the include)
TileGrass tileGrass = TileGrass(0); is a definition, and it's in a header, so you'll get a multiple definition error if you include the header multiple times. If you want a global (rethink that), you have to use extern.

Related

Problem including base header in all child headers [duplicate]

This question already has answers here:
When can I use a forward declaration?
(13 answers)
Closed 4 years ago.
I have a base class, which is declared in the following header file:
#pragma once
#include "StateHandler.hpp"
namespace ta {
class GameState {
public:
// ...
};
} /* ta */
Then, I have two children, which look like this:
#pragma once
#include "../GameState.hpp"
namespace ta {
class DefaultState: public ta::GameState {
public:
// ...
};
} /* ta */
and
#pragma once
#include "../GameState.hpp"
namespace ta {
class WorldMapState: public ta::GameState {
public:
// ...
};
} /* ta */
When trying to compile that, I get errors, that GameState was not declared in the second of the two children I include. When I remove the #pragma once from the GameState.hpp, it says that GameSate gets redefined. I get why that happens, but I can't find a way to fix that.
UPDATE: Using include-guards doesn't work either. I get the following error, when using #pragma once or include-guards:
In file included from /[...]/include/statemachine/gamestates.hpp:2,
from /[...]/include/common.hpp:4,
from /[...]/include/statemachine/gamestates/../StateHandler.hpp:5,
from /[...]/include/statemachine/gamestates/../GameState.hpp:4,
from /[...]/include/statemachine/gamestates/DefaultState.hpp:4,
from /[...]/include/statemachine/gamestates.hpp:1,
from /[...]/include/common.hpp:4,
from /[...]/source/main.cpp:1:
/[...]/include/statemachine/gamestates/WorldMapState.hpp:7:47: error: expected class-name before '{' token
class WorldMapState: public ta::GameState {
^
And this is the error I get, when I don't use include-guards or #pragma once in the GameState.hpp (this error appears 3 times):
In file included from /[...]/include/common.hpp:5,
from /[...]/source/main.cpp:1:
/[...]/include/statemachine/GameState.hpp:4:11: error: redefinition of 'class ta::GameState'
class GameState {
^~~~~~~~~
In file included from /[...]/include/statemachine/gamestates/WorldMapState.hpp:4,
from /[...]/include/statemachine/gamestates.hpp:2,
from /[...]/include/common.hpp:4,
from /[...]/include/statemachine/gamestates/../StateHandler.hpp:5,
from /[...]/include/statemachine/gamestates/../GameState.hpp:1,
from /[...]/include/statemachine/gamestates/DefaultState.hpp:4,
from /[...]/include/statemachine/gamestates.hpp:1,
from /[...]/include/common.hpp:4,
from /[...]/source/main.cpp:1:
/[...]/include/statemachine/gamestates/../GameState.hpp:4:11: note: previous definition of 'class ta::GameState'
class GameState {
According to this answer #pragma once has unfixable bugs. It should never be used.
You can use header guards like below
#ifndef HEADER_H
#define HEADER_H
// Header file code
#endif
#pragma once is not a standard even it's supported by many compilers should not used to guard header files instead use #ifndef. As there is no standard behavior for #pragma once, you shouldn't assume that the behavior will be the same on all compiler.

Multpile definition error of a header declared variable when there's just one definition/declaration [duplicate]

This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 5 years ago.
I have a header file where I've defined a structure and its variable 'editor' and am using it in multiple files. I have not declared it anywhere else, yet it gives me multiple declaration error. I've also tried using #ifndef but to no avail.
This is my header file:
editorlib.h
#ifndef ED_LIB
#define ED_LIB
//#include files
struct terminalProperties {
int rows,cols;
struct termios origTerm;
int mode;
}editor;
int TERMINATE=0;
//function definitions
#endif
My editorlib.cpp
#ifndef EDITORLIBRARY_H
#define EDITORLIBRARY_H
#include "editorLibrary.h"
getAttr() {
tcgetattr(STDIN_FILENO, TCSAFLUSH, &editor.origterm);
}
//further code
#endif
Driver file vi_editor.cpp:
#ifndef MAIN_H
#define MAIN_H
#include "editorLibrary.h"
int main(){
//some code
while(1){
//some code
if(TERMINATE)
break;
}
//some code
return 0;
}
#endif
My normal.cpp:
#ifndef NORMALMODE_H
#define NORMALMODE_H
#include "editorLibrary.h"
void normalMode() {
editor.mode = 1;
//further code
}
#endif
My command.cpp:
#ifndef COMMANDMODE_H
#define COMMANDMODE_H
#include "editorLibrary.h"
void commandMode() {
editor.mode = 2;
//further code
}
#endif
Similarly I have a few other files where I'm not declaring the editor variable but just using it in a similar manner as above. I can't seem to find why it tell me about multiple declaration.
Multpile definition of a header declared variable
This is already a violation of the One Definition Rule. The simple answer is "don't". You can only declare in a header, via extern, and define in a single .cpp file.

Dividing project to .h and .cpp

I wanted to divide my project into smaller parts cause it started to be unreadable(1000+ lines) and i have some problem with specified .h and .cpp that need to use definitons defined in other files.
Project contains following files:
main.cpp
RPG.h and .cpp
Hero.h and .cpp
Globaldefs.h and .cpp
#ifndef Hero_h
#define Hero_h
#include "Globaldefs.h"
#include "RPG.h"
#include <vector>
using namespace std;
extern class NPC;
extern class Inventory;
class Hero
{
protected:
(...)
Inventory inventory;
(...)
public:
vector<Mob*>::iterator TryAttack(vector <Mob*>& monsters, int & number);
vector<NPC*>::iterator TryTalk(vector <NPC*>& _NPCs, int & number);
};
(...)
#endif
declaration above is from Hero.h file and compilator finds error in line Inventory inventory; (that class is outside, declared in RPG.h and defined in RPG.cpp): 'Hero::inventory' uses undefined class 'Inventory' RPG d:\programming\rpg\rpg\rpg\hero.h 23 I completely don't understand why Mob(other class from RPG.h and .cpp) work properly and NPC defined as extern(too in RPG.h) as well.
#ifndef RPG_h
#define RPG_h
#include "Globaldefs.h"
#include "Hero.h"
#include <vector>
using namespace std;
class Mob;
class NPC;
class Fight;
class Item;
extern class Hero;
(...)
class Meat : public Item
{
(...)
public:
virtual void ActivateEffect(Hero* _hero) { _hero->AddHp(15); };
};
#endif
this is RPG.h file, and there, compilator says that something went wrong in line
virtual void ActivateEffect(Hero* _hero) { _hero->AddHp(15); };
there is: use of undefined type 'Hero' RPG d:\programming\rpg\rpg\rpg\rpg.h 97 and left of '->AddHp' must point to class/struct/union/generic type RPG d:\programming\rpg\rpg\rpg\rpg.h 97
i reserched many sites, but everywhere people has problems with simple adding files to main.cpp, not making internal connections beetween files.
Inclusion guards prevent you to include RPG.h in Hero.h and vice-versa.
What you did is to forward declare Hero in RPG.h, which is good.
But then you did:
virtual void ActivateEffect(Hero* _hero) { _hero->AddHp(15); };
and the compiler needs to know the structure of Hero class to link it to AddHp method. You just cannot do that.
Do that instead (just declare the method):
virtual void ActivateEffect(Hero* _hero);
And remove the #include "Hero.h" line.
Then in the RPG.cpp file do:
#include "Hero.h"
void RPG::ActivateEffect(Hero* _hero) { _hero->AddHp(15); }
We don't see the code for the Inventory problem, but I suppose that's the same problem.
To summarize:
you can include file A.h in file B.h but in that case you cannot include file B.h in A.h
but you can forward declare class B in A.h and reference the pointer/reference on that class, as long as you don't try to use B methods in the header file.
to use B methods in A object, just include B.h in A.cpp and have access to all B method in A.cpp. Some inline methods cannot be implemented in the .h file when they use methods/members of B
You have a circular dependency between RPG.h and Hero.h, and RPG.h line 97, only the forward declaration (extern class Hero;) is visible so you can only reference pointers and references to whole Hero objects and cannot reference members of Hero.
The circular dependency may itself indicate poor design in any case.

Forward Declaration issue [duplicate]

This question already has answers here:
How are circular #includes resolved?
(4 answers)
Why aren't my include guards preventing recursive inclusion and multiple symbol definitions?
(3 answers)
Closed 9 years ago.
I currently ran into a situation which I do not understand and would appreciate it if someone could explain to me why this is happening and how I may resolve it.
Suppose I have two header files Client.h and Order.h with classes Client and Order respectively.This is an overview
FileName: Order.h
#ifndef Order_Header
#define Order_Header
.....
#include "Client.h"
class Order
{
public:
enum OrderType{open,close};
Client db; // ---> Line A
};
#endif
FileName: Client.h
#ifndef Client_Header
#define Client_Header
.....
#include "Order.h"
class Client
{
public:
void someMethod(Order::OrderType e);
};
#endif
Now if this project is compiled I get an error at line A saying it does not recognize the Client Class. However If I move the enum from the Order Class to the Client class
such that the enum is accessed using Client::OrderType then I get no errors. What is happening here any suggestions on how I can resolve this arent my header guards working ?
You have an circular dependency between client and order. Its best to try to avoid it. But if you need it you can forward declare your classes (and templates) and use references and pointers to them. The classes can not be used because they are incomplete.
#ifndef Order_Header
#define Order_Header
class Client; // forward declaration
class Order
{
public:
enum OrderType{open,close};
// the following declarations work:
Client* db_1;
Client& db_2;
std::shared_ptr<Client> db_3;
// the following declaration does not work, because of incomplete type
Client db_4;
};
#endif
The same with Client.h. You should note that the declaration of your methods have to be changed from passing Client to Client const& as you cant use the incomplite type Client in your interface. Client&, Client*, std::shared_ptr<Client> and variations are complete types.
In your implementation files you can include all headers and your types are complete and you can work with them.
It's beacause when the compile the Order.h file he go first to the #include "Client.h" the it's compil it before Order.h and when he arrive to void someMethod(Order::OrderType e); Order is not defined. To solve it try
#ifndef Order_Header
#define Order_Header
.....
// #include "Client.h" Put it only on your cpp file
Class Client;
Class Order
{
public:
enum OrderType{open,close};
Client db; ---> Line A
}
#endif
FileName: Client.h
#ifndef Client_Header
#define Client_Header
.....
#include "Order.h"
Class Client
{
public:
void someMethod(Order::OrderType e);
}
#endif
`

c++ how to include (circular dependency)?

I have Environment.h file:
#include <windows.h>
#include "interfaces.h"
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
class Environment {};
#endif
and i have Interfaces.h file:
#ifndef INTERFACES_H
#define INTERFACES_H
class IMoving {
public:
virtual void Move() = 0;
};
#endif
in interface IMoving i would like to get an Environment class, to know how to move
class IMoving {
public:
virtual void Move(Environment*) = 0;
};
if i want to do this i need to include environment.h
#include "Environment.h"
and here i'm getting an error, becouse Environment.h - includes Interfaces.h and Interfaces.h - includes Environtment.h. So how to make it work ?
Sorry for spelling mistakes
For circular dependencies one can use Forward declaration(s)
In Interfaces.h just above interface definition, forward declare Environment as follows:
class Environment;
Then when you implement IMoving in a class, you will include Environment.h in its implementation (cpp) file.
You can read more about Forward declaration here.
It looks like you misspelled the class name a few times (Environtment,Envrirontment). Could that be the origin of your issue?
Otherwise I typically use the Forwarded Declaration