Circular Dependency
In a situation where two types need to know about each other the solution is to use forward declaration and aggregation-by-reference in at least one of them.
You can use forward declared type T:
- pointer-to-T
- reference-to-T
- function parameter type
- function return value
You can't use forward declared type T:
- derive from T
- member variable
- instantiate
- use its member function
- use its member variable
one.hxx:
1 #ifndef ONE_HXX
2 #define ONE_HXX
3
4
5 struct two; // forward declaration
6
7
8 struct one {
9 one( two const& x, two const* y );
10
11 private:
12 two const& x;
13
14 two const* y;
15 };
16
17
18 #endif
one.cxx:
1 #include "one.hxx"
2 #include "two.hxx"
3
4
5 one::one( two const& x, two const* y )
6 : x( x ),
7 y( y ) {
8 }
two.hxx:
1 #ifndef TWO_HXX
2 #define TWO_HXX
3
4
5 struct one; // forward declaration
6
7
8 struct two {
9 two( one const& x, one const& y )
10
11
12 private:
13 one const& x;
14
15 one const& y;
16 };
17
18
19 #endif
two.cxx:
1 #include "one.hxx"
2 #include "two.hxx"
3
4
5 two::two( one const& x, one const* y )
6 : x( x ),
7 y( y ) {
8 }
Access to member functions and variables.
The following is just a hack and using it usually means a design flow:
1 struct B; // forward declaration
2
3 struct A
4 {
5 // _Declaration_ of the function that will need access to B's members.
6 // We can't define it yet, as we know nothing about B's members.
7 void f(B&);
8 void g() { }
9
10 };
11
12 struct B
13 {
14 void f(A& a)
15 {
16 a.g();
17 }
18
19 void g() { }
20 };
21
22 void A::f(B& b) // _definition_ of function that uses B's member
23 {
24 b.g(); // B::g() is declared so we can use it here.
25 }
It can of course be applied to data members of forward declared class as well.
