473,473 Members | 1,873 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

circular include

9 New Member
I'm having a problem which I think has to do with the circular use of inlcuding header files.
The short version of my code would look a bit like this, I think:
GameEngine.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef GAME_ENGINE
  2. #define GAME_ENGINE
  3.  
  4. #include "Player.h"
  5.  
  6. class GameEngine
  7. {
  8. public:
  9.     GameEngine ();
  10. // ..
  11.  
  12. private:
  13.     // ..
  14.     Player* players[2];
  15. };
  16.  
  17. #endif
  18.  
Player.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef PLAYER
  2. #define PLAYER
  3.  
  4. #include "GameEngine.h"
  5.  
  6. // This class contains pure virtual functions!
  7. class Player
  8. {
  9. public:
  10.     // ..
  11. protected: 
  12. //..
  13. private:
  14.     GameEngine* game; // line 37
  15. // ..
  16. };
  17.  
  18. #endif
  19.  
These are the errors I'm getting:
Player.h:37: error: ISO C++ forbids declaration of `GameEngine' with no type
Player.h:37: error: expected `;' before '*' token

If I change line 37 into GameEngine Game; (so it's not a pointer anymore), the error changes to:
Player.h:37: error: `GameEngine' does not name a type

If I remove line 37, a lot more errors are found:
Players\RandomPlayer.cpp:12: error: expected class-name before '{' token
Players\RandomPlayer.cpp:19: error: expected `,' or `...' before "note"
Players\RandomPlayer.cpp:19: error: ISO C++ forbids declaration of `Notification' with no type
Players\RandomPlayer.cpp:28: error: class `RandomPlayer' does not have any field named `Player'
Players\RandomPlayer.cpp:34: error: `name' undeclared (first use this function)
Players\RandomPlayer.cpp:34: error: (Each undeclared identifier is reported only once for each function it appears in.)
GameEngine.h:19: error: `Player' has not been declared
GameEngine.h:19: error: ISO C++ forbids declaration of `parameter' with no type
GameEngine.h:30: error: ISO C++ forbids declaration of `Player' with no type
GameEngine.h:30: error: expected `;' before '*' token
Player.cpp:38: warning: unused variable 'move'
:: === Build finished: 10 errors, 1 warnings ===

All of these errors seem to have to do with types like Player and GameEngine not being known. Does anybody have any idea how I can repair this?

Complete header files: (there are of course more files, so if it is necessary to see those to, just ask for them)

GameEngine.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef GAME_ENGINE
  2. #define GAME_ENGINE
  3.  
  4. #include <vector>
  5.  
  6. #include "Board.h"
  7. #include "Player.h"
  8. #include "Players.h"
  9.  
  10. class GameEngine
  11. {
  12. public:
  13.     GameEngine ();
  14.     GameEngine (std::vector<CellOwner>);
  15.  
  16.     Board* getBoard () const;
  17.     int getTurns () const;
  18.     bool end () const;
  19.     bool setPlayer (const CellOwner, Player*);
  20.     bool removePlayer (const CellOwner);
  21.     void swapPlayers ();
  22.     void restart ();
  23.     void next ();
  24.     bool undo ();
  25.     bool redo ();
  26.  
  27. private:
  28.     unsigned int turn;
  29.     Board* board;
  30.     Player* players[2];
  31.  
  32.     std::vector<unsigned int> moves;
  33. };
  34.  
  35. #endif
  36.  
Player.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef PLAYER
  2. #define PLAYER
  3.  
  4. #include <string>
  5. #include <list>
  6.  
  7. #include "GameEngine.h"
  8. #include "Board.h"
  9.  
  10.  
  11. enum Notification { CLEAR };
  12.  
  13. class Player
  14. {
  15. public:
  16.     virtual ~Player();
  17.  
  18.     void addObserver (Player* observer);
  19.     void removeObserver (Player* observer);
  20.     void makeMove (const Board*);
  21.     std::string getName () const;
  22.     bool canLearn () const;
  23.     bool isHuman () const;
  24.  
  25.     virtual void setName (const std::string name) = 0;
  26.     virtual void learn (const Board*, const int) = 0;
  27.     virtual void notify (const Notification) = 0;
  28.     virtual int thinkMove (const Board*) = 0;
  29.     virtual void giveTurn () = 0;
  30. protected: // Protected, because observers can be asked for help
  31.     std::list<Player*> observers;
  32.     std::string name;
  33.     bool turn;
  34.  
  35.     Player (const bool, const bool);
  36. private:
  37.     GameEngine* game;
  38.     const bool human;
  39.     const bool teachable;
  40. };
  41.  
  42. #endif
  43.  
  44.  
Thanks for any help!
Feb 23 '07 #1
6 7568
Banfa
9,065 Recognized Expert Moderator Expert
I'm having a problem which I think has to do with the circular use of inlcuding header files.
Correct!

The problem is GameEngine.h includes Player.h but has (correctly) set an double include protection symbol so when Player.h tries to include GameEngine.h it gets an empty file because of this double include protection. Then class Player tries to use class GameEngine, however because the copy of GameEngine.h that Player.h included was empty the class GameEngine has not been defined and you get all the errors.

However all is not lost. If you look at class GameEngine you will see it only uses class Player in the context of a pointer to Player (i.e. doesn't try to access any members) and in fact class Player only uses class gameEngine in the context of a pointer to GameEngine. In this case the compiler only needs to reserve space for a pointer so it only needs to know that the class exists not what it's details are.

There is a way to inform a the compiler that a class exists (or will exist) but define any of it's details, it is called "forward declaring the class (or structure)" and the syntax is

Expand|Select|Wrap|Line Numbers
  1. class GameEngine;
  2.  
You can remove the inclusion of the headers and forward declare your classes instead, in GameEngine.h this looks like

Expand|Select|Wrap|Line Numbers
  1. #ifndef GAME_ENGINE
  2. #define GAME_ENGINE
  3.  
  4. class Player.h;
  5.  
  6. class GameEngine
  7. {
  8. public:
  9.     GameEngine ();
  10. // ..
  11.  
  12. private:
  13.     // ..
  14.     Player* players[2];
  15. };
  16.  
  17. #endif
  18.  
Feb 23 '07 #2
Jordi
9 New Member
Thank you very much for you quick reply! I had figured parts of what you said out, but your explanation was very good and I understand a lot better now.

I'm assuming though that you meant to write "class Player;" instead of "class Player.h;".

This deals with my problem very well, but now I have another (far less important question):
From your explanation, I gather that I can always use forward declaration in header files where I'm only using a pointer to an object. I would still need to include the header files in the *.cpp files (because I'll be using methods of the forward declared class), so I might as well do it in a header file. However, it isn't strictly necessary there since a forward declaration would do. So, what would be considered good practice?
Feb 23 '07 #3
Banfa
9,065 Recognized Expert Moderator Expert
I'm assuming though that you meant to write "class Player;" instead of "class Player.h;".
Err, yes I did.

From your explanation, I gather that I can always use forward declaration in header files where I'm only using a pointer to an object. I would still need to include the header files in the *.cpp files (because I'll be using methods of the forward declared class), so I might as well do it in a header file. However, it isn't strictly necessary there since a forward declaration would do. So, what would be considered good practice?
This sort of thing is a lot down to personal choice.

For instance in some companies #including from header files at all is frowned upon and you tend to have long lists of headers in you c/cpp files. Personally I don't agree with this because those long lists of headers just get very unweidly and you often end up with unrequired headers in files.

Another not uncommon approach is to include all headers into another single header file in the correct order and then include that header into your c/cpp files. If you use precompiled headers this doesn't have too much effect of compile time. I don't like this approach because it is a bit of a sledge hammer approach.

So I say if a header requires another header then include it, however try not to let the header inclusion go too deep, not more than 1 or 2 levels.

As to forward declaration it is required to get round the problem you have had but I don't think it is very elegant so my opinion is that you should arrange your header inclusion to reduce the amount of required forward declaration to a minimum.

However note this is all opinion, I have not seen many "best practices" covering the topic of forward declaration.
Feb 23 '07 #4
Jordi
9 New Member
Thanks again for your reply!

The solution worked for a while. I forward declared GameEngine in Player.h and then included it in Player.cpp, where I could use all of GameEngine's public methods. However, I now derived a class from Player and put it in a file called RandomPlayer.cpp. I've created no header file for this, because this class is really basic and the public interface is almost exactly the same as Player's. However, Including both Player.h and GameEngine.h in RandomPlayer.cpp gives me this errors:
E:\Jordi\Development\Projects\FourFun\lib\Players\ RandomPlayer.cpp:38: error: invalid use of undefined type `struct GameEngine'
E:\Jordi\Development\Projects\FourFun\lib\Players\ ..\Player.h:10: error: forward declaration of `struct GameEngine'
:: === Build finished: 2 errors, 0 warnings ===

I have also forward declared Player in GameEngine.h, so those files are not directly linking to eachother anymore.

Does anyone know why this is and what I can do about it?
Feb 25 '07 #5
Jordi
9 New Member
Never mind, the new problem was similar to the old one, I just didn't see it.
Feb 26 '07 #6
Banfa
9,065 Recognized Expert Moderator Expert
Never mind, the new problem was similar to the old one, I just didn't see it.
Hooray, because while I was aware of the second question I had kind of lost the thread (or was it is plot???).

Happy to know your current problems are solved.
Feb 26 '07 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: Mohit Gupta | last post by:
Hi all, I have just started working on VC++ .Net and have problem with circular dependencies of 2 files. I created 2 forms "Form1" and "Form2", which respectively created 2 .h files, Form1.h...
3
by: crichmon | last post by:
Any general advice for dealing with circular dependencies? For example, I have a situation which, when simplified, is similar to: ///////////// // A.h class A { public: int x;
6
by: Markus Dehmann | last post by:
I have a circular dependency between two classes. The FAQ hint about a forward declaration does not help in my case ( How can I create two classes that both know about each other?) Error:...
16
by: Kiuhnm | last post by:
Is there an elegant way to deal with semi-circular definitions? Semi-circular definition: A { B }; B { *A }; Circular reference: A { *B }; B { *A }; The problems arise when there are more...
4
by: ro86 | last post by:
Hello everyone! I am a newbie to C++ (~1 Week experience) and I have a few months of experience with object-oriented languages (Objective-C). I am currently working just for fun on a particle...
3
by: JCB | last post by:
Hi, I have two C file which are referencing in a circular way. To simplify I use an example with car : Suppose I have a program for cars. I have car.c, structure car and functions...
1
by: Booser | last post by:
// Merge sort using circular linked list // By Jason Hall <booser108@yahoo.com> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> //#define debug
6
by: T Koster | last post by:
After a few years of programming C, I had come to believe that I finally knew how to correctly organise my structure definitions in header files for mutually dependent structures, but I find myself...
5
by: fomas87 | last post by:
Hi guys, I'm writing a framework for an sdl gui in c++, but got stuck on the circular dependency, I've read a lot of articles about resolving dependencies and about forward declaration but none of...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.