Friday, February 25, 2011

C++: Circular Dependencies

Circular Dependencies is an 'error' in programming that involve two files including each other. Here is the example:

// file A.h
#include B.h

class A {
public: 
   A() {
      B b;
   }
}


// file B.h
#include A.h

class B {
public: 
   B() {
      A b;
   }
}

Compiling this will result an error since the compiler will loop infinitely through these 2 files. But once I found this necessary when I try to build my simple Game Engine. Let say there are class Player and Bullet. The player will shoot Bullet, hence it would be good to include Bullet in class Player. However the buller requires collision checking with players. So it also necessary to include Player in Bullet. Of course there are many way to trick this out (the use of Event based pattern is the most common solution), but I tried to keep my Engine simple and fast, so I'll stick with the simpler method: try to trick the circular dependencies. This is what you need to do:

1. Make sure the header file does not access any of the included Object method. This can be safely done if you split the header with the implementation perfectly. 

2. Create a forward declaration in the header file. This declaration means nothing, it just allow us to use variable B to declare an Object.

// file A.h
class B;

class A {
public: 
   A() {
      B b;
   }
}

// file B.h
class A;

class B {
public: 
   B() {
      A b;
   }
}

3. Include the header in the implementation 

// file A.cpp
#include B.h;
/* implementation here */

// file B.cpp
#include A.h;
/* implementation here */

4. Make sure that you implement this only to classes that has a circular dependencies. In my experience, when the program getting larget, its hard to track which one has a dependencies to which, so start from the very beginning phase of the program development. A circular dependencies compilation error message is very hard to translate. It's a generic compilation error and can be cause by many things. So building a program heavily based on this is not advisable. 

happy programming :)


No comments: