473,545 Members | 1,759 Online
Bytes | Software Development & Data Engineering Community
+ 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\RandomP layer.cpp:12: error: expected class-name before '{' token
Players\RandomP layer.cpp:19: error: expected `,' or `...' before "note"
Players\RandomP layer.cpp:19: error: ISO C++ forbids declaration of `Notification' with no type
Players\RandomP layer.cpp:28: error: class `RandomPlayer' does not have any field named `Player'
Players\RandomP layer.cpp:34: error: `name' undeclared (first use this function)
Players\RandomP layer.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 7574
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.cp p. 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.cp p gives me this errors:
E:\Jordi\Develo pment\Projects\ FourFun\lib\Pla yers\RandomPlay er.cpp:38: error: invalid use of undefined type `struct GameEngine'
E:\Jordi\Develo pment\Projects\ FourFun\lib\Pla yers\..\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
1482
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 and Form2.h and so as 2 classes, "Form1" and "Form2". Now I want to use object of Form1 inside Form2 and object of Form2 in Form1.
3
2037
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
2839
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: "field `foo' has incomplete type" for the following code: #include <iostream> #include <vector>
16
2819
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 semi-circular definitions and
4
4765
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 system. All the particles are controlled by a "server". The server performs all kinds of operations on them (updating, drawing etc.). The particles...
3
7262
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 prototypes of car.c are in a file car.h
1
12829
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
2818
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 stumped again with this little love triangle. Here is some background: m_commands.h defines - struct command_callbacks, which contains - a...
5
2949
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 them seem to work for me. Basically I've got the Component abstract class which is the base class for all elements like Buttons, Labels, CheckBoxes,...
0
7467
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7656
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7807
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7419
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
1
5326
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
4944
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3450
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3442
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
703
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

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.