this is my first question here.
Writing some code, i receive this error from g++: "Entity was not declared in this scope", in this context:
#ifndef Psyco2D_GameManager_
#define Psyco2D_GameManager_
#include <vector>
#include "Entity.h"
namespace Psyco2D{
class GameManager{J
private:
std::vector<Entity> entities;
};
}
#endif
This is the content of Entity.h:
#ifndef Psyco2D_Entity_
#define Psyco2D_Entity_
#include <string>
#include "GameManager.h"
#include "EntityComponent.h"
namespace Psyco2D{
class Entity{
friend class GameManager;
private:
/* Identificatore */
std::string _name;
/* Components list */
std::map<const std::string, EntityComponent*> components;
protected:
Entity(const std::string name);
public:
inline const std::string getName() const{
return this->_name;
}
void addComponent(EntityComponent* component, const std::string name);
EntityComponent* lookupComponent(const std::string name) const;
void deleteComponent(const std::string name);
};
}
#endif
If i use std::vector<class Entity> instead of std::vector<Entity> it works.
Why?
Thanks to all =)
The problem is you have a cyclic dependency. Take out #include "GameManager.h" in Entity.h, since you don't actually need it in that header. (Up-vote this answer, which first pointed it out.)
Note the guards are actually the problem; but don't take them out! You just need to minimize the includes you have, and declare (and not define) types when possible. Consider what happens when you include Entity.h: As some point it includes GameManager.h, which in turn includes Entity.h. At this point, Entity.h already has its header guard defined, so it skips the contents. Then the parsing of GameManager.h continues, where upon it runs into Entity, and rightfully complains it is not defined. (Indeed, this is still the process of including GameManager.h in the first inclusion of Entity.h, far before Entity is defined!)
Note your numerous edits demonstrate why it's important to post real code, not re-synthesized code. You need real details to get real answers.
Old:
Entity is in the Psyco2D namespace. You need to specify that:
class GameManager{
private:
std::vector<Psyco2D::Entity> entities;
};
Assuming the first snippet is part of GameManager.h you have a circular header dependency. I believe you can fix this by changing the GameManager.h include in Entity.h to class GameManager; instead.
Additionally as GMan noted, Entity is in a namespace and you need to qualify Entity with the namespace name.
Remove the Psyco2D-namespace and it will work without declaring "class Entity".
Related
I have this piece of code
#ifndef STATION_H
#define STATION_H
#include <vector>
#include "Dispenser.h"
#include "Cashier.h"
//class Cashier;
class Station
{
private:
int price;
int dispenser_count;
int cashier_count;
std::vector<Dispenser> dispensers;
std::vector<Cashier> cashiers;
public:
Station(int, int, int);
int GetPrice() const { return price; }
Dispenser *LookForUnoccupiedDispenser(int &id);
Dispenser *GetDispenserByID(int id);
Cashier *LookForUnoccupiedCashier();
};
#endif // STATION_H
When I have the class Cashier line commented, the compiler fails with a 'Cashier' was not declared in this scope error even though Cashier.h was included. Uncommenting it makes it possible to compile but I'm concerned that it shouldn't be happening.
Cashier.h
#ifndef CASHIER_H
#define CASHIER_H
#include "Station.h"
class Station;
class Cashier
{
private:
bool busy;
Station *at_station;
public:
Cashier(Station *employer);
bool IsBusy() const { return busy; }
};
#endif // CASHIER_H
How is it possible? It's clearly declared in the header file and as far as I know, #include does nothing more than pasting the content of a file into another one.
Thank you for the answers in advance!
Your station.h includes cachier.h. This is an example of cyclic dependency. Given that you only have a pointer to Station in Cachier I'd suggest removing the dependency of station.h and forward declare it.
An #include is literally nothing more than verbatim copy and paste of that file into the current compilation unit. The guards protect you from the effect of an infinite include cycle, but due to the guards one of the #includes does nothing, i.e. does NOT suck in the declaration (nor definition) of the respective class. This results in the error you get. In station.h the compiler has never seen any mention of the Cachier type when it sees the Station type.
I have three classes.
first class:
#ifndef C_LINKED_LIST_H
#define C_LINKED_LIST_H
class CLinkedList {
private:
//removed code for brevity
public:
// removed code for brevity
};
#endif
second class:
#ifndef C_SSF_FOLDER_CONTAINER_H
#define C_SSF_FOLDER_CONTAINER_H
#include "C_SSF_Folder.h"
#include "CLinkedList.h"
class C_SSF_Folder_Container {
private:
// removed code for brevity
public:
int Add_Folder(C_SSF_Folder *_pcl_SSF_Folder);
C_SSF_Folder *Get_Folder(int _i_Index);
C_SSF_Folder *Get_Folder(char *_pch_Name);
//^-----errors
};
#endif C_SSF_FOLDER_CONTAINER_H
my third class
#ifndef C_SSF_FOLDER_H
#define C_SSF_FOLDER_H
#include <windows.h>
#include <fstream>
#include "C_SSF_Folder_Container.h"
using namespace std;
class C_SSF_Folder {
public:
private:
C_SSF_Folder_Container cl_SSFFC_Folder_Container;
public:
};
#endif
my third class C_SSF_Folder.
I am including "C_SSF_Folder_Container.h"
and declaring a C_SSF_Folder_Container container.
Before declaring the variable it compiles fine. After I declare it
I get syntax errors in my C_SSF_Folder_Container
Severity Code Description Project File Line Suppression State
Error C2061 syntax error: identifier 'C_SSF_Folder' CSSFileSystem\projects\cssfilesystem\cssfilesystem\c_ssf_folder_container.h 16
Error C2061 syntax error: identifier 'C_SSF_Folder' CSSFileSystem \projects\cssfilesystem\cssfilesystem\c_ssf_folder_container.h 19
As I myself look into it I think there is a problem because my C_SSF_Folder is including C_SSF_Folder_Container.
and C_SSF_Folder_Container is including C_SSF_Folder
but the defines should take care of it? Other than that I have no clue what's the problem.
Everything is typed correctly.
You've got a circular #include -- C_SSF_Folder_Container.h #includes C_SSF_Folder.h and C_SSF_Folder.h #includes C_SSF_Folder_Container.h.
This would cause an infinite regress (and a compiler crash) except that you've got the #ifndef/#define guards at the top of your files (as you should); and because of them, instead what you get is that one of those two .h files can't see the other one, and that's why you get those errors.
The only way to fix the problem is to break the circle by deleting one of the two #includes that comprise it. I suggest deleting the #include "C_SSF_Folder.h" from C_SSF_Folder_Container.h and using a forward declaration (e.g. class C_SSF_Folder; instead.
C_SSF_Folder.h and C_SSD_Folder_Container.h are including each other(Circular Dependency).
When the compiler compiles C_SSF_Folder_Container object, it needs to create a C_SSF_Folder object as its field, however, the compiler needs to know the size of C_SSF_Folder object, so it reaches C_SSF_Folder object and tries to construct it. Here is the problem, when the compiler is constructing C_SSF_Folder object, the object has a C_SSF_Folder_Container object as its field, which is a typical chicken and egg question, both files depends on each other in order to compile.
So the correct way to do it is to use a forward declaration to break the circular dependency(including each other).
In your C_SSF_Folder.h, make a forward declaration of C_SSF_Folder_Container.
#include <windows.h>
#include <fstream>
using namespace std;
class C_SSF_Folder_Container;
class C_SSF_Folder {
public:
private:
C_SSF_Folder_Container cl_SSFFC_Folder_Container;
public:
};
#endif
Finally, include C_SSF_Folder_Container.h in your C_SSF_Folder.cpp.
You can also learn more in the following links:
Circular Dependency (Wiki):
https://en.wikipedia.org/wiki/Circular_dependency
Forward Declaration by Scott Langham
What are forward declarations in C++?
I'm currently trying to make a game in C++. In my code I'm trying to nest my variables so that my main doesn't have a lot of includes. My problem right now though is that the value of my variables in my class aren't changing. Stepping through the code it shows it setting the value, but it doesn't work. Anyone know what's going on? Thank you in advance.
This is what I have so far:
Location.h
#ifndef LOCATION_H
#define LOCATION_H
#include <string>
class Location
{
public:
Location(void);
Location(std::string name);
~Location(void);
std::string GetName();
void SetName(std::string value);
private:
std::string m_Name
};
#endif
Location.cpp
#include "Location.h"
Location::Location(void): m_Name("") {}
Location::Location(std::string name): m_Name(name) {}
Location::~Location(void)
{
}
std::string Location::GetName()
{return m_Name;}
void Location::SetName(std::string value){m_Name = value;}
PlayerStats.h
#ifndef PLAYERSTATS_H
#define PLAYERSTATS_H
#include "Location.h"
class PlayerStats
{
public:
PlayerStats(void);
~PlayerStats(void);
Location GetLocation();
void SetLocation(Location location);
private:
Location m_Location;
};
#endif
PlayerStats.cpp
#include "PlayerStats.h"
PlayerStats::PlayerStats(void): m_Location(Location()) {}
PlayerStats::~PlayerStats(void)
{
}
Location PlayerStats::GetLocation(){return m_Location;}
void PlayerStats::SetLocation(Location location){m_Location = location;}
main.cpp
#include <iostream>
#include "PlayerStats.h"
using namespace std;
PlayerStats playerStats = PlayerStats();
int main()
{
playerStats.GetLocation().SetName("Test");
cout<< playerStats.GetLocation().GetName()<<endl;
return 0;
}
Your immediate issue is that
Location GetLocation();
returns a copy of the location, so when you call SetName here:
playerStats.GetLocation().SetName("Test");
You're changing the name of the temporary copy, and the change is lost as soon as the semicolon is hit.
More broadly, this kind of design (nesting classes and nesting includes so that main doesn't have a lot of includes, and using a.b.c() style code to access nested members) isn't great C++ style:
Having a bunch of source files that (transitively) include a bunch of header files means that changing a single header file will trigger recompilations of a bunch of source files. Compile times can be a significant issue in larger C++ projects, so reducing compile times by controlling #include's is important. Read up on "forward declarations" for more information.
Writing code like a.b.c() is considered bad object-oriented design, because it reduces encapsulation: not only does the caller have to know about a's details, it has to know about b's also. Sometimes this is the most expedient way to write code, but it's not something to be blindly done just to reduce #include's. Read up on "Law of Demeter" for more information.
If you want to set the result of playerStats.GetLocation(), you could make GetLocation() pass-by-reference (use ampersand, &, on the return argument). Otherwise you are just setting values in a temporary copy of PlayerStats::m_Location.
Alternatively, you could use the SetLocation() function.
I can't solve this circular dependency problem; always getting this error:
"invalid use of incomplete type struct GemsGame"
I don't know why the compiler doesn't know the declaration of GemsGame even if I included gemsgame.h
Both classes depend on each other (GemsGame store a vector of GemElements, and GemElements need to access this same vector)
Here is partial code of GEMELEMENT.H:
#ifndef GEMELEMENT_H_INCLUDED
#define GEMELEMENT_H_INCLUDED
#include "GemsGame.h"
class GemsGame;
class GemElement {
private:
GemsGame* _gemsGame;
public:
GemElement{
_gemsGame = application.getCurrentGame();
_gemsGame->getGemsVector();
}
};
#endif // GEMELEMENT_H_INCLUDED
...and of GEMSGAME.H:
#ifndef GEMSGAME_H_INCLUDED
#define GEMSGAME_H_INCLUDED
#include "GemElement.h"
class GemsGame {
private:
vector< vector<GemElement*> > _gemsVector;
public:
GemsGame() {
...
}
vector< vector<GemElement*> > getGemsVector() {
return _gemsVector;
}
}
#endif // GEMSGAME_H_INCLUDED
Remove the #include directives, you already have the classes forward declared.
If your class A needs, in its definition, to know something about the particulars of class B, then you need to include class B's header. If class A only needs to know that class B exists, such as when class A only holds a pointer to class B instances, then it's enough to forward-declare, and in that case an #include is not needed.
If you deference the pointer and the function is inline you will need the full type. If you create a cpp file for the implementation you can avoid the circular dependecy (since neither of the class will need to include each others .h in their headers)
Something like this:
your header:
#ifndef GEMELEMENT_H_INCLUDED
#define GEMELEMENT_H_INCLUDED
class GemsGame;
class GemElement {
private:
GemsGame* _gemsGame;
public:
GemElement();
};
#endif // GEMELEMENT_H_INCLUDED
your cpp:
#include "GenGame.h"
GenElement::GenElement()
{
_gemsGame = application.getCurrentGame();
_gemsGame->getGemsVector();
}
Two ways out:
Keep the dependent classes in the same H-file
Turn dependency into abstract interfaces: GemElement implementing IGemElement and expecting for IGemsGame, and GemsGame implementing IGemsGame and containing a vector of IGemElement pointers.
Look at the top answer of this topic: When can I use a forward declaration?
He really explains everything you need to know about forward declarations and what you can and cannot do with classes that you forward declare.
It looks like you are using a forward declaration of a class and then trying to declare it as a member of a different class. This fails because using a forward declaration makes it an incomplete type.
I'm trying to refactor my code so that I use forward declarations instead of including lots of headers. I'm new to this and have a question regarding boost::shared_ptr.
Say I have the following interface:
#ifndef I_STARTER_H_
#define I_STARTER_H_
#include <boost/shared_ptr.hpp>
class IStarter
{
public:
virtual ~IStarter() {};
virtual operator()() = 0;
};
typedef boost::shared_ptr<IStarter> IStarterPtr;
#endif
I then have a function in another class which takes an IStarterPtr object as argument, say:
virtual void addStarter(IStarterPtr starter)
{
_starter = starter;
}
...
IStarterPtr _starter;
how do I forward declare IStarterPtr without including IStarter.h?
I'm using C++98 if that is of relevance.
Shared pointers work with forward declared types as long as you dont call * or -> on them so it should work to simply write :-
class IStarter;
typedef boost::shared_ptr<IStarter> IStarterPtr;
You need to include <boost/shared_ptr.hpp> of course
Though it would add a header file, you could put that in a separate header file :
#include <boost/shared_ptr.hpp>
class IStarter;
typedef boost::shared_ptr<IStarter> IStarterPtr;
and then include it both in IStarter.h and in your other header, avoiding code duplication (though it's quite small in this case).
There might be better solutions though.
You can't forward declare typedefs in C++98 so what I usually do in this case is pull out the typedefs I need an put them into a types.h file, or something similar. That way the common type code is still separated from the definition of the class itself.
There is a way but you need to include the boost header in your file :
#include <boost/shared_ptr.hpp>
class IStarter;
typedef boost::shared_ptr<IStarter> IStarterPtr;
// ...
virtual void addStarter(IStarterPtr starter)
{
_starter = starter;
}
// ...
IStarterPtr _starter;