"Recursive Dependencies" - How to do?

Started by
6 comments, last by yaustar 16 years, 5 months ago
Well, hi again. This time I've got a quick question on compiler #include dependencies.. Say for example, I've got a header H1, that depends on H2, which in turn depends on H3, which depends on H1 also. So, how am I supposed to manage something like this? I've tried declaring the classes in a seperate header file, which will get me a step further, but then fails to find the "real" definition and just spits out errors about incomplete types. Help?
Advertisement
Why does H3 depend on H1? Anyway, your 'solution' will probably be to look into forward declarations of classes. A better solution might be to work around such circular dependencies in the first place.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

I've been working on an Engine framwork of such, which is Event based. The problem being Event depends on an Entity class for pointers.

Anyway, thanks. I'll take a look at it. In the future I hope to avoid the issue anyway ;)
For each file, figure out if you really need to #include another file.

Let's take H1 as an example, #including H2. Why? What does it need out of H2?

Here's a simple example:

/* H1.h */
#include "H2.h" // declares Bar
class Foo
{
public:
void Run(Bar* bar);
};

/* H2.h */
class Bar
{
/* whatever */
};


Since you don't actually make use of Bar objects in H1 (you only indicate that Run, defined in the .cpp file, will use Bar _in the .cpp file_), you don't need the header. So you could make H1 look like this instead:

/* H1.h */
class Bar; // forward declare
class Foo
{
public:
void Run(Bar* bar);
};


Because you didn't use/store Bar (you only mentioned a pointer parameter), you only need to let the compiler know the name, hence the forward declaration. The cpp file, however, will need to #include "H2.h"

That is very informal... You might get some more complete descriptions from others here.

Aside from circular dependencies, this can help reduce compile time, so it's a nice thing to do.

Also, you might consider that such a circular dependency as you describe can often, though not always, indicate a design flaw. Consider your design and see if there are ways to simplify.
This occurs a lot in code like this, so much so that I wonder if there is a pattern name for it (or maybe it's an anti-pattern). A lot of people are uncomfortable with the cyclical dependency and rightfully so as it often indicates a bad design decision.

There are ways to refactor what you have described to not have the cyclical dependency but they are very ugly in my experience. They also typically involve dynamic casts which make some people uncomfortable. I've come to think of it like this: if the classes are maintained and reused together then this heavy coupling (and cyclical dependency) is acceptable, but if they aren't then I need to refactor.
Have you tried using #Ifdef?

For example

#ifndef __CAMERA_H__#define __CAMERA_H__#include <neededHeader.h>class CCamera{private:	//private stuffpublic:	// public stuff}		#endif


Also, from my understanding, it's proper practice to separate class declarations from class member functions.
^^ What mossmoss said.

If you only need to include the class so you can declare a pointer, then

Instead of:
#include "MyClass.h" //contains the definition of MyClass
Just write:
class MyClass;
This article should explain it more fully.

Steven Yau
[Blog] [Portfolio]

This topic is closed to new replies.

Advertisement