tags:

views:

77

answers:

3

Hi,

I'm getting a compiler error with this header file:

#ifndef GAME1_H  
#define GAME1_H  
#include "GLGraphics.h"  
#include "DrawBatch.h"  
class GameComponent;  
class Game1 {  
private:  
    GLGraphics graphics;  
 GameComponent components;
 void updateDelegates();  
 void Run();  
};  

class GameComponent {  
private:  
 static int index;  
protected:  
 Game1 game;  
public:  
 GameComponent();  
 GameComponent(Game1 game);  
 void Update(int);  
 void Dispose();  
};  

class DrawableGameComponent: public GameComponent  
{  
private:  
 GLGraphics graphics;  
 DrawBatch drawBatch;  
public:   
 DrawableGameComponent();  
 DrawableGameComponent(Game1);  
 void Draw();  
};  

#endif

I see the problem is that Game1 needs the full definition of GameComponent, and that GameComponent needs the full definition of Game1. I had way too much trouble having these in separate headers, so that's why they're together. Is there any way I can do this without completely changing the implementation of one of the classes?

Thanks!

+3  A: 

To do what you're trying you'll need to have a pointer to one of your classes rather than having it as a member.

For example:


class A;
class B;
class A {
   B b;
};

class B {
   A a;
};

This cannot work. It causes a circular structure. The constructor for A will call the constructor for B, which calls the constructor for A, and so on infinitely.

Instead, try:


class A;
class B;
class A {
   B *b;
};

class B {
   A *a;
};

A word of warning, though. If you are setting something up this way, there's a pretty good chance your design is flawed. You should reconsider how you are solving your problem.

JoshD
+7  A: 

Think about the computer's memory for a second here.

class B;

class A {
    byte aa;
    B ab;
};

class B {
    byte bb;
    A ba;
};

A x;

Now the question the compiler needs to answer is How much space should I reserve for x?

Let's see. The first byte of x is byte aa;. Easy enough. That's 1 byte.
Next comes B ab;. Let's see what's in there.
The first byte of x.ab is a byte bb;. That's 2 bytes for x so far.
Next, is a A ba;. Let's see what's in there.
The first byte of x.ab.ba is a byte aa;. That's 3 bytes for x so far.
And so on and so forth ad infinitum.
How big is x? The correct answer is of course *** OUT OF CHEESE ERROR ***.

The compiler doesn't actually do this because it knows it can't handle this case - so the syntax doesn't allow circular containment in the first place.


Here's a diagram of the contents of x in this example:
Diagram


UPDATE

Apparently, I forgot to include a solution here. Now that you understand what the problem is, the solution should be pretty simple. Use pointers. Either use a pointer from A to B and let B include A as it already does, or vice versa, or use two pointers. Then, you won't have circular inclusion - if B doesn't include a copy of A but just a pointer to it, that fixes the entire issue here.

configurator
+1 for out of cheese error
Zack
Nice image. And also nice error. +1.
JoshD
Nice image: I would upvote it if you included a **solution** to the issue :)
Matthieu M.
@Matthieu: You make a good point. I didn't even notice it was missing!
configurator
+1  A: 

At the risk of being off-topic: you can do this in C#, but unless the nested members are all load-on-demand you'll get an immediate crash when you first instantiate either.

egrunin