By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,758 Members | 1,223 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,758 IT Pros & Developers. It's quick & easy.

Problem with #includes, friend classes, and forward declarations.

boxfish
Expert 100+
P: 469
Hi everyone, I'm working on a 3d maze game, and I just messed up the classes so it won't compile, and I need help sorting it out. There's a class Maze, whose members are, among other things, a list of the walls, the user who is an object of class MazePerson, and a yellow square who is an object of class MazeMonster. MazePerson and MazeMonster are both inherited from class MazeThing, which takes care of stuff like collisions. MazePerson, MazeMonster, and MazeThing used to be structs inside of class Maze like this:

Maze.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef MAZE_H
  2. #define MAZE_H
  3. ...
  4. using namespace std;
  5.  
  6. class Maze {
  7. public:
  8.     ...
  9. private:
  10.     ...
  11.     struct MazeThing {
  12.         ...
  13.     };
  14.     struct MazePerson : public MazeThing {
  15.         ...
  16.     };
  17.     struct MazeMonster : public MazeThing {
  18.         ...
  19.     };
  20.     ...
  21.     MazePerson person;
  22.     MazeMonster monster;
  23.     ...
  24. };
  25.  
  26. #endif
  27.  
Now I want to take MazeThing, MazePerson, and MazeMonster out of class Maze, give each of them their own header file, let them be real classes, make Maze be a friend of all of them, and make all of them friends of class Maze. Here's what I did:

Maze.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef MAZE_H
  2. #define MAZE_H
  3. ...
  4. #include "MazePerson.h"
  5. #include "MazeMonster.h"
  6.  
  7. using namespace std;
  8.  
  9. class Maze {
  10. public:
  11.     friend class MazeThing;
  12.     ...
  13. private:
  14.     ...
  15.     MazePerson person;
  16.     MazeMonster monster;
  17.     ...
  18. };
  19.  
  20. #endif
  21.  
MazeThing.h:
Expand|Select|Wrap|Line Numbers
  1. #ifndef MAZETHING_H
  2. #define MAZETHING_H
  3.  
  4. class Maze;
  5.  
  6. class MazeThing {
  7. public:
  8.     friend class Maze;
  9. protected:
  10.     ...
  11.     Maze *myMaze;
  12.     ...
  13. };
  14.  
  15. #endif
  16.  
MazePerson.h
Expand|Select|Wrap|Line Numbers
  1. #ifndef MAZEPERSON_H
  2. #define MAZEPERSON_H
  3.  
  4. #include "MazeThing.h"
  5.  
  6. class Maze;
  7.  
  8. class MazePerson : public MazeThing {
  9. public:
  10.     friend class Maze;
  11.     ...
  12. };
  13.  
  14. #endif
  15.  
MazeMonster.h
Expand|Select|Wrap|Line Numbers
  1. #ifndef MAZEMONSTER_H
  2. #define MAZEMONSTER_H
  3.  
  4. #include "MazeThing.h"
  5.  
  6. class Maze;
  7.  
  8. class MazeMonster : public MazeThing {
  9. public:
  10.     friend class Maze;
  11.     ...
  12. };
  13.  
  14. #endif
  15.  
But wherever I use MazeThing's member myMaze in MazeThing.cpp I get these errors:

invalid use of undefined type `struct Maze'
forward declaration of `struct Maze'

I've tried changing around the #includes and forward declarations, but I always get errors. Any help would be greatly appreciated.
Jul 12 '08 #1
Share this Question
Share on Google+
8 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
This compiles:
Expand|Select|Wrap|Line Numbers
  1. class MazeThing {
  2.         //...
  3.     };
  4. struct MazePerson : public MazeThing {
  5.         //...
  6.     };
  7. struct MazeMonster : public MazeThing {
  8.         //...
  9.     };
  10.  
  11.  
  12. #ifndef MAZE_H
  13. #define MAZE_H
  14. //...
  15. //#include "MazePerson.h"
  16. //#include "MazeMonster.h"
  17.  
  18. using namespace std;
  19.  
  20. class Maze {
  21. public:
  22.     friend class MazeThing;
  23.     //...
  24. private:
  25.     //...
  26.     MazePerson person;
  27.     MazeMonster monster;
  28.     //...
  29. };
  30. #endif
  31.  
Basically, all I did was change your struct MazeThing to class MazeThing. I did that because you declared friend class rather than friend struct.
Jul 13 '08 #2

boxfish
Expert 100+
P: 469
Thanks so much for your reply! But MazeThing already was a class. But when I put everything in one file like you did, it works! So it seems like I have to figure out how to get the #includes right so the classes end up in that order after the preprocessor does its thing. Oh wait, maybe it's because I didn't use namespace std on all of them...
Okay I didn't, let me try that...
Thanks again!
Jul 13 '08 #3

boxfish
Expert 100+
P: 469
Okay, that didn't work. There's another error I can get instead if, instead of a forward declaration of class Maze in MazeThing.h, I #include "Maze.h".
It goes like this:

In file included from Maze.h
from MazeThing.h
from MazeThing.cpp
parse error before `{' token
parse error before `}' token
In file included from Maze.h
from MazeThing.h
from MazeThing.cpp
parse error before `{' token
parse error before `}' token
In file included from MazeThing.h
from MazeThing.cpp
field `person' has incomplete type
field `monster' has incomplete type

When it says `{' and `}' tokens, It points to the opening and closing braces of a class:
Expand|Select|Wrap|Line Numbers
  1. #ifndef MAZEMONSTER_H
  2. #define MAZEMONSTER_H
  3.  
  4. #include "MazeThing.h"
  5.  
  6. using namespace std;
  7.  
  8. class Maze;
  9.  
  10. class MazeMonster : public MazeThing { // << This one
  11. public:
  12.     friend class Maze;
  13.     ...
  14. }; // << and this one..
  15.  
  16. #endif
  17.  
It does this in MazePerson.h and MazeMonster.h.

When It says field monster and field person, it points to the MazePerson person and MazeMonster monster members of class Maze.

Does anyone have any ideas?

I'm using Dev-C++ 4.9.8.0 on Windows XP, if that helps.

Thanks for any help you can give me.
Jul 13 '08 #4

P: 20
How does your MazeThing constructor look?
Jul 15 '08 #5

weaknessforcats
Expert Mod 5K+
P: 9,197
class MazeMonster : public MazeThing { // << This one
When you compiler says parse error before {, it is trying tell you that when the { was encountered it was unexpected. Therefore, the parse knows there is trouble either with the { or the code preceding it. Like maybe MazeThing.

Keep in mind that you are using templates. The compiler requires the templates to precede any use of the templates. You either a) put all the templates together in the correct order in one header file and include it or b) use multiple header files that are included in the correct order.

You cannot have some of your templates in other files because templates are not code. They are patterns the compiler copies, substitutes a real type for the template type and this becomes the real code.
Jul 15 '08 #6

boxfish
Expert 100+
P: 469
Hi, Thanks for your replies. My problem magically went away just now. I put everything into one file, and that made it work, and I just put it back into separate files and it still works. I thought that maybe not everything had been recompiled, so I clicked rebuild all, and it still worked. Ok, I just found out what I changed that made it work: MazePerson.cpp and MazeMonster.cpp now both include Maze.h instead of their own header files. It seems weird to me that that made it work, but I guess If they include their own header files, stuff ends up in the wrong order, and by including Maze.h, they indirectly include their own header files, because Maze.h includes them.
@mkborregaard: MazeThing currently does not have a constructor. Maze initializes its MazeThing objects' variables in its own constructor. That is not good and I need to fix it.
@weaknessforcats: I don't know what you mean by templates. I thought templates were functions and classes that could be instantiated to work with new variable types as needed. I didn't think I was using them. Does it have to do with inheritance? Eventually I want to go through all the files, figure out (by trial and error) which includes are unnessecary (I have such a hard time spelling that), and get rid of them. They seem like a mess right now.
Thanks again.
Jul 15 '08 #7

P: 20
@mkborregaard: MazeThing currently does not have a constructor. Maze initializes its MazeThing objects' variables in its own constructor. That is not good and I need to fix it.
OK. I was just wondering whether your problem was related to the uninitialized Maze* pointer (which i guess you intend to initialize in the MazeThing constructor to point to the Maze object owning MazeThing). Cool you got it solved, though.
Jul 16 '08 #8

boxfish
Expert 100+
P: 469
OK. I was just wondering whether your problem was related to the uninitialized Maze* pointer (which i guess you intend to initialize in the MazeThing constructor to point to the Maze object owning MazeThing). Cool you got it solved, though.
Yeah. But if it was a problem with an uninitialized pointer, I probably would have gotten an access violation, not a compiler error. I'm going to go try to make it a multi-story maze with ramps leading between the levels now.
Jul 16 '08 #9

Post your reply

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