Circular dependency

From Wikipedia, the free encyclopedia

A Circular dependency is a situation which can occur in programming languages wherein the definition of an object includes the object itself.

Circular dependencies are usually used to implement callback functionality in programs. However, occurrences of circular dependencies should normally be limited, since they make the resulting object-models unclear and unstructured, and are hence considered a bad programming habit. Circular dependencies will also prevent some very primitive automatic garbage collectors (those that use reference counting) from deallocating objects.

Contents

[edit] Circular dependencies in C++

Implementation of circular dependencies in C/C++ can be a bit tricky, due to the requirement that any class or structure definition must be placed above their usage in the same file. A circular dependency between classes A and B will thus both require the definition of A to be placed above B, and the definition of B to be placed above A, which of course is impossible. A forward declaration trick is therefore needed to accomplish this.

Circular dependencies in C/C++ are implemented by using forward declarations. The following example illustrates how this is done.

  • File a.h:
#ifndef A_H
#define A_H

class B;        //forward declaration

class A {
public:
        B* b;
};
#endif //A_H
  • File b.h:
#ifndef B_H
#define B_H

class A;        //forward declaration

class B {
public:
        A* a;
};
#endif //B_H
  • File main.cpp:
#include "a.h"
#include "b.h"

void main() {
        A a;
        B b;
        a.b = &b;
        b.a = &a;
}

[edit] Self-reference example

Following is another example of forward declaration, which might be useful if the application needs a self-sustaining array of objects which is able to add and remove objects from itself during run-time:

  • File a.h:
class A {
public:
    static A *first, *last;
    A *previous, *next;

    A();
    ~A();
};

The static variables first and last have to be defined, because their declaration does not reserve memory space for them. Note: static variables do not change from object to object and stay the same for this given class.

  • File a.cpp:
#include "a.h"

A *A::first, *A::last; // don't put the word static here, that will cause an error

A::A() {
    previous=last;
    previous->next=this;
    last=this;
    next=0;
}

A::~A {
    previous->next=next;
    next->previous=previous;
}

[edit] External links

[edit] See also

  • Circular Definition