Sign in to follow this  
Endar

circular include hell (C++)

Recommended Posts

Okay, I am really hating the ridiculous intricacies of these 3 classes. CEngine, CDebugConsole, CDebugConsoleEventReceiver. CEngine needs to call functions inside CDebugConsole. CDebugConsole needs to call the constructor (non-default) of CDebugConsoleEventReceiver. CDebugConsoleEventReceiver needs to call functions inside CEngine. So, CEngine includes CDebugConsole, CDebugConsole includes CDebugConsoleEventReceiver and CDebugConsoleEventReceiver includes CEngine. I don't think that there is another way I'll be able to do this. I have a forward declaration of CDebugConsoleEventReceiver in the CDebugConsole header file, but it turns out that it's not going to work because I need to call a non-default constructor. Am I completely screwed? Do I need to scrap my current design for this bit and just re-write everything?

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
I have a forward declaration of CDebugConsoleEventReceiver in the CDebugConsole header file, but it turns out that it's not going to work because I need to call a non-default constructor.
Can you not call the constructor from the CPP file, instead of the header?

If you just define the classes in the header, and don't implement any methods, there's no problem.

Share this post


Link to post
Share on other sites
also make sure you don't use the trouble classes by value in your header file..here's a quick example

Circular dependency way

// lets say this is a header file that causes
// the circular dependency problem
#include <foo.h>

class MyClass{
public:
foo value;
};


Non-circular dependency way

// forward declare the class
class foo;

class MyClass{
public:
foo* value;
};
// make sure you include foo.h in your source file
// wherever MyClass is implemented


[edit]
This is what Steve is saying, I misread it the first time =)

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
Okay, I am really hating the ridiculous intricacies of these 3 classes.

CEngine, CDebugConsole, CDebugConsoleEventReceiver. CEngine needs to call functions inside CDebugConsole. CDebugConsole needs to call the constructor (non-default) of CDebugConsoleEventReceiver. CDebugConsoleEventReceiver needs to call functions inside CEngine.

So, CEngine includes CDebugConsole, CDebugConsole includes CDebugConsoleEventReceiver and CDebugConsoleEventReceiver includes CEngine.

I don't think that there is another way I'll be able to do this.

I have a forward declaration of CDebugConsoleEventReceiver in the CDebugConsole header file, but it turns out that it's not going to work because I need to call a non-default constructor.

Am I completely screwed? Do I need to scrap my current design for this bit and just re-write everything?


Your whole design is not completly flawed, but there is something weird, obviously. What you want to achieve is very similar to the observer pattern, but in your case the subject creates its own observers (in fact, it creates events that will in turn call the update functions in the observer (CEngine)). A possible solution should be to use the observer pattern in a correct way:

class DebugConsoleEventReceiver
{
public:
virtual void update(DebugConsoleEvent *e) = 0;
};

class DebugConsole
{
std::vector<DebugConsoleEventReceiver*> mObservers;
public:
void addObserver(Observer* o) { mObservers.push_back(o); }
void fireEvent(DebugConsoleEvent *e)
{
for (size_t i=0; i<mObservers.size(); i++) {
mObservers[i]->update(e);
}
}
};

class Engine : public DebugConsoleEventReceiver
{
DebugConsole mConsole;
public:
Engine() { mConsole.addObserver(this); }
void update(DebugConsoleEvent *e) { ... }
};


HTH,

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this