I've these 2 files, but the interface (and the compiler) give me this error, can you help me find what is wrong?Is really strange... should I define all body of my methods in the .cpp file?
//GameMatch.h
#pragma once
#include "Player.h"
namespace Core
{
class GameMatch
{
private:
const static unsigned int MAX_PLAYERS=20;
unsigned int m_HumanControlled;
Score* m_LastDeclaredScore;
Score* m_LastScore;
unsigned int m_MaxPlayers;
Player* m_Players[MAX_PLAYERS];
unsigned int m_PlayerTurn;
inline void NextTurn() { m_PlayerTurn=(m_PlayerTurn+1U)%m_MaxPlayers; }
public:
GameMatch(void);
~GameMatch(void);
void RemovePlayer(Player* _player);
inline Player* getPlayingPlayer() { return m_Players[m_PlayerTurn]; }
};
}
and
//Player.h
#pragma once
#include "IController.h"
#include "GameMatch.h"
#include <string>
#include <Windows.h>
using namespace Core::Controller;
using namespace std;
namespace Core
{
class Player
{
private:
IController* m_Controller;
unsigned int m_Lives;
GameMatch* m_GameMatch;
string m_Name;
bool m_TurnDone;
public:
inline void Die()
{
m_Lives-=1U;
if (m_Lives<1) m_GameMatch->RemovePlayer(this);//m_GameMatch is the first error
}
inline const string& getName() { return m_Name; }
inline bool IsPlayerTurn() { return (m_GameMatch->getPlayingPlayer()==this); }//m_GameMatch is the second error
virtual void Play()=0;
inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3)
{
m_GameMatch=_gameMatch;
m_Name=name;
m_Lives=lives;
}
inline void WaitTurn() { while(!IsPlayerTurn()) Sleep(1); }
virtual ~Player()
{
delete m_Controller;
}
};
}
But as you can see, m_GameMatch is a pointer, so I don't understand why this error, maybe for "recursive inclusion" of header files...
UPDATE 1:
//GameMatch.h
#pragma once
#include "Score.h"
#include "Player.h"
namespace Core
{
class GameMatch
{
private:
const static unsigned int MAX_PLAYERS=20;
unsigned int m_HumanControlled;
Score* m_LastDeclaredScore;
Score* m_LastScore;
unsigned int m_MaxPlayers;
Player* m_Players[MAX_PLAYERS];
unsigned int m_PlayerTurn;
inline void NextTurn();
public:
GameMatch(void);
~GameMatch(void);
void RemovePlayer(Player* _player);
inline Player* getPlayingPlayer();
};
}
and
//Player.h
#pragma once
#include "IController.h"
#include "GameMatch.h"
#include <string>
#include <Windows.h>
using namespace Core::Controller;
using namespace std;
namespace Core
{
class Player
{
private:
IController* m_Controller;
unsigned int m_Lives;
GameMatch* m_GameMatch;
string m_Name;
bool m_TurnDone;
public:
inline void Die();
inline const string& getName();
inline bool IsPlayerTurn();
virtual void Play()=0;
inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3);
inline void WaitTurn();
virtual ~Player();
};
}
These are the 2 headers now, however it's still not working, if I don't include Player.h and forward declare a class in this way inside GameMatch.h:
class Player;
It works, however what if I want use some Player methods?I should re-forward declare everything... isn't this what header files are done for? I can include an header file in a lot of places... why can't I do it in this case?
SOLUTION:
The answer is from Alf P. Steinbach on chat:
yes, and the answer you got seems to be correct. the cyclic header dependency is a problem. there might be other problems also, but the cyclic dependency is a big one.
you don't need a full definition of a class in order to use T*.
so the usual breaking of the cycle is to just forward-declare a class, like
class Player;
that tells the compiler that Player is a class, so you can use Player* and Player&, and even declare member functions that return Player (although you can't define such a function until Player class is fully defined)
well as a concrete example, all that's needed for the Core::GameMatch class definition is a forward declaration of class Player.
then in implementation file you can include "player.h".
if it's needed for GameMatch implementation.
if you draw the files as little boxes and draw arrows to show includes, you'll see that that gets rid of the cyclic dependency
This said, he explain that the answer I got is the correct one so I'll mark OJ's
You should definitely avoid the cyclic header include.
Break the content of your functions out into .cpp files instead of putting everything in header files. Also, rather than #include things every time, just forward declare instead.
If you remove the cyclic include, your code will most likely work.
Related
I have two projects, one is a sample (which compiles without error) and looks like this (first few lines shown only):
Working Example
#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/Surface.h"
#include "cinder/gl/gl.h"
#include "cinder/gl/Texture.h"
#include "cinder/Rand.h"
#include "cinder/qtime/QuickTimeGl.h"
using namespace ci;
using namespace ci::app;
using namespace std;
class QTimeAdvApp : public App {
public:
void prepareSettings( Settings *settings );
void setup();
void keyDown( KeyEvent event );
void fileDrop( FileDropEvent event );
void update();
void draw();
void addActiveMovie( qtime::MovieGlRef movie );
void loadMovieUrl( const std::string &urlString );
void loadMovieFile( const fs::path &path );
};
Note especially the line: void addActiveMovie( qtime::MovieGlRef movie );
The other project, which needs to make use of the same library (Quicktime OpenGL within LibCinder), tries to do something similar - one again an extract:
Use in Project
#pragma once
#include "AbstractContent.h"
#include "cinder/gl/Texture.h"
#include "cinder/Tween.h"
#include "AbstractTransition.h"
#include "cinder/qtime/QuickTimeGl.h"
namespace TH {
class VideoContent : public AbstractContent {
public:
VideoContent();
~VideoContent();
virtual void setup();
void loadMovie(ci::Url url);
void loadLocalMovie(ci::fs::path path);
void setPreloadedMovie(ci::qtime::MovieGlRef movie);
This one throws a compiler error: No member named 'qtime' in namespace 'cinder'
Notice again the virtually identical line: void setPreloadedMovie(ci::qtime::MovieGlRef movie); In fact, you can use the full qualified name ci:qtime:MovieGlRef in the first example and it compiles just fine (as expected).
What on earth is going on here? Why does the "Use in Project" version throw a compiler error: No member named 'qtime' in namespace 'cinder'?
Just for clarity, the QuickTimeGl.h file in turn includes another file which definitely declares the namespace and the type def:
namespace cinder { namespace qtime {
typedef std::shared_ptr<class MovieGl> MovieGlRef;
Am I missing something? I'm pretty sure I'm including the correct header file, as before, and even trying to use the fully qualified namespace but still the compiler doesn't find the definition?
Have you tried referencing the global namespace, with ::ci::qtime rather than simply ci::qtime? This should not make a difference, but sometimes C++ compilers trip over these kind of things.
I'm trying to create a vector which will store objects. I have added to the header file of the class as a private data member.
I am trying to initialize this vector as being empty (so that I can add objects to it later on in the program) but when I compile this program to test, this error is returned:
...error: '_bookingVector' was not declared in this scope|
I think the problem is with my initialization list on my default constructor(_bookingVector is obviously the vector):
Schedule::Schedule() : _bookingVector()
{ }
Is my syntax wrong? Or are vectors initialized differently?
Here is my code:
Schedule.h
#ifndef SCHEDULE_H
#define SCHEDULE_H
#include "Booking.h"
#include <vector>
using namespace std;
class Schedule
{
public:
Schedule();
void AddBooking(int bday, int btime, int btrainer, int bid);
void RemoveBooking(int bday, int btime);
void DisplaySchedule();
void DisplayAvailableTimeSlots();
//For Testing
void DisplayDebug();
private:
vector<Booking> _bookingVector;
};
#endif // SCHEDULE_H
Schedule.cpp
#include "Schedule.h"
#include "Booking.h"
#include <vector>
#include <iostream>
Schedule::Schedule() : _bookingVector()
{ }
void AddBooking(int bday, int btime, int btrainer, int bid){
Booking bookingObject(bday, btime, btrainer, bid);
_bookingVector.push_back(bookingObject);
}
void DisplayDebug(){
for(int i = 0; i < _bookingVector.size(); ++i){
cout << _bookingVecotr[i] << endl;
}
}
I'm very eager to learn what I'm doing wrong and fix it.
The issue is not with the constructor, which looks fine if unnecessary1. The issue is that you have defined AddBooking and DisplayDebug as non-member functions, but these should be members in order to access other members of the class.
Modify the definitions to be in the scope of the Schedule class thus:
void Schedule::AddBooking(int bday, int btime, int btrainer, int bid) { ...
^^^^^^^^^^
void Schedule::DisplayDebug(){ ...
^^^^^^^^^^
Also, don't say using namespace std in a header file (I'd go further and say don't say it anywhere but there isn't universal agreement on that.)
1 Your default constructor does not do anything that the compiler-generated one wouldn't do. You can safely remove it.
I know there are plenty of questions like these, but I couldn't find a solution that worked for me. Anyways, I have 4 files, two header files and two cpp files, one implementation and one main.
Header File 1
#ifndef SORTEDINTERFACE_H
#define SORTEDINTERFACE_H
using namespace std;
template<class ListItemType>
class sortedInterface
{
public:
virtual int sortedGetLength() const = 0;
virtual bool sortedIsEmpty() const = 0;
virtual bool sortedInsert(const ListItemType& newItem) = 0;
virtual bool sortedRemove(const ListItemType& anItem) = 0;
virtual bool sortedRetrieve(const ListItemType& anItem) = 0;
virtual int getItemCount () = 0;
private:
virtual int locatePosition(const ListItemType& anItem) = 0;
};
#endif // SORTEDINTERFACE_H_INCLUDED
Header File 2
#ifndef SORTED_H
#define SORTED_H
#include "sortedInterface.h"
using namespace std;
template<class ListItemType>
class sorted : public sortedInterface<ListItemType>
{
public:
sorted();
int sortedGetLength() const;
bool sortedIsEmpty() const;
bool sortedInsert(const ListItemType& newItem);
bool sortedRemove(const ListItemType& anItem);
bool sortedRetrieve(const ListItemType& anItem);
int getItemCount();
private:
static const int DEFAULT_LIST_SIZE = 10;
ListItemType items[DEFAULT_LIST_SIZE];
int itemCount;
int maxItems;
int locatePosition(const ListItemType& anItem);
};
#include "sorted.cpp"
#endif // SORTED_H
CPP File
#include "sorted.h"
#include <cstddef>
using namespace std;
template<class ListItemType>
sorted<ListItemType>::sorted() : itemCount(0), maxItems(DEFAULT_LIST_SIZE)
{
} // end default constructor
Main CPP File
#include <iostream>
#include "sorted.h"
#include <cstddef>
using namespace std;
int main()
{
sorted<string> test;
return 0;
}
When I compile I get the errors/warnings
1. redefinition of 'sorted::sorted()
2. sorted::sorted()' previously declared here
When I comment out the #include "sorted.cpp" at the end of header file #2, it works, but then in my main file, it doesn't regonize my sorted test object.
Any help would be great, thanks in advance.
are you compiling sorted.cpp also . i think you should not .
If you're adding the sorted.cpp file at the end, then you must realize that sorted.cpp is not a separate module -- it is just the implementation of your template class implementation. Therefore you should remove the first three lines from that .cpp file.
#include "sorted.h"
#include <cstddef>
using namespace std;
Those lines above should not be in the template implementation file.
Also, I would rename sorted.cpp to sorted.ipp or some other extension to something indicating it is just a template implementation file and not a separate source module to be compiled.
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.