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.
Related
Greetings oh mighty coders,
I am a beginner and in a bit of trouble here.
There is my baseclass (sensor.h):
class sensor
{
private:
int sensor_id;
string sensor_name;
string sensor_type;
float reading;
public:
sensor();
sensor(int, char*, char*);
~sensor();
/* Few extra methods here */
};
... and I want to create 4 other classes that inherit from my baseclass sensor
(temperaturesensor, humiditysensor... and so on).
#include "sensor.h"
class temperaturesensor:public sensor
{
public:
Temperatursensor(int, char*,char*);
~Temperatursensor();
/* Few extra methods here */
};
Thing is: Every single one of these classes has to be in its own .cpp/.h file and then be included and used in my main.cpp.
using namespace std;
#include <xyz.h>
/* Other libaries here */
....
#include "temperaturesensor.h"
#include "humiditysensor.h"
int main()
{
sensor* station[2];
station [0] = new temperaturesensor(x,y,z);
station [1] = new humiditysensor(x,y,z);
}
If I include one of them it's no biggie. However: If I use multiple ones I get an redefinition error.
error C2011: 'sensor': 'class' typeredefinition
c:\users\name\desktop\project\sensor.h 14
error c2011: 'temperaturesensor' : 'class' typeredefinition
What can I do to workaround this? Note that I am not allowed to use #pragma once
Sorry for my stupidity and thanks in advance!
You must use:
#ifndef FILE_H
#define FILE_H
.. normal code here
#endif
or
#pragma once
but too, I think, that sensor schould be abstract class and you schould use virtual destructor.
One more think is that array is numerate from 0.
you forgot to use the include guards in your header class,
this is redefining your base class everytime you use it.
so, just do a
#pragma once
or a normal include guard
#ifndef YOURFILENAME_H
#define YOURFILENAME_H
.. normal code here
#endif
Then you will not have the multiple definition error.
The definition of the class sensor is coming from both "temperaturesensor.h"
and "humiditysensor.h". Use guards https://en.wikipedia.org/wiki/Include_guard or #pragma once: https://en.wikipedia.org/wiki/Pragma_once
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
`
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C header file loops
Original Question:
I always had problems understanding why the following gives errors:
something.h
#ifndef SOMETHING_H
#define SOMETHING_H
#include "somethingelse.h"
#endif
somethingelse.h
#ifndef SOMETHINGELSE_H
#define SOMETHINGELSE_H
#include "something.h"
#endif
Why does this give errors?
1) SOMETHING_H is not defined
2) SOMETHING_H becomes defined, somethingelse.h get included
3) SOMETHINGELSE_H is not defined, becomes defined, and something.h gets included
4) SOMETHING_H is defined, jump to #endif, this should be the end of it?
EDIT:
turns out it doesn't give any errors at all. However the following does:
something.h
#pragma once
#include "somethingelse.h"
class something {
int y;
somethingelse b;
};
somethingelse.h
#pragma once
#include "something.h"
class somethingelse {
something b;
int x;
};
And it is logical, because the class 'something' is not yet defined when 'somethingelse' needs an instance of that class.
The problem is solved by forward definition:
something.h
#pragma once
class somethingelse;
class something {
int y;
somethingelse* pB; //note the pointer. Correct me if I'm wrong but I think it cannot be an object because the class is only declared, not defined.
};
in the .cpp, you can include "somethingelse.h", and make instances of the class.
Your description is exactly correct, except that there is no error at all. Add pragma message("Some text") (assuming Visual Studio) at various places to trace the flow.
As other posters have already noted, your header files most likely contain classes that mutually require each other's definition, and that is the cause of the problem. This sort of problem is usually solved by
Using forward references where possible
Moving #includes to CPP files where possible
That's exactly what happens.
This is called an "include guard" and is used to avoid infinitely recursive includes.
Animal
|
Mammal
/ \
TwoLegged - FourLegged
/ \
Human Lion
I have this class hierarchy, each class defined in it's own header. Now when I include both
Human.h and Lion.h in the same place, I get a Mammal redefinition error.
error C2011: 'Mammal' : 'class' type redefinition
This because Mammal.h is included in both TwoLegged and OneLegged classes.
I'm not sure however, how I could resolve this cyclic dependency in headers, as I cannot change the class hierarchy.
Anybody care to assist?
EDIT:
Mammal header
#ifndef MAMMAL_H
#define MAMNAL_H
#include "stdafx.h"
#include "Animal.h"
class Mammal : public Animal
{
public:
Mammal::Mammal();
virtual Mammal::~Mammal();
std::string mammal_name();
int mammal_age();
int mammal_expectedlifedays();
bool mammal_hunter();
int mammal_power();
int mammal_birthrate();
bool mammal_alive();
protected:
Mammal::Mammal(const std::string& mname, int mexpectedlifedays, int mage, bool mhunter, int mpower, int mbirthrate, bool malive) : Animal(mname, mexpectedlifedays, mage,mhunter, mpower, mbirthrate, malive)
{}
private:
};
#endif
The errors given by the compiler:
error C2011: 'Mammal' : 'class' type redefinition
see declaration of 'Mammal'
error C2504: 'Mammal' : base class undefined
error C2614: 'TwoLegged' : illegal member initialization: 'Mammal' is not a base or member
Note: It's not homework, else I would have tagged it as such.
#pragma once
Add that at the very top of all your header files.
However, keep in mind that even though it is very well supported by compilers, it's not a standard.
You need to use include guards. The typical form is:
#ifndef NAME_OF_HEADER_H
#define NAME_OF_HEADER_H
// Rest of header code here.
#endif
Since #include in C++ just does a copy-paste of the text in the current file if the same header gets included twice that text will result in duplicate class definitions. What the include guard does is prevent the multiple inclusion of the same header.
EDIT: The problem is that you check for definition of MAMMAL_H and then define MAMNAL_H (note the N in the defined version). I always copy-paste to generate my include guards for precisely this reason.
I guess you forgot include guards. Use #ifndef /#ifdef/ #endif as John suggested.
#ifndef MAMMAL_H
#define MAMMAL_H
... definition of mammal
#endif