Usually in C++ when I need interdependencies between classes, I use forward declarations in the header files and then include both header files in each cpp file.
How
You can utilize fine-grained headers:
// A.forward.hpp
template<typename T> struct A;
// A.decl.hpp
#include "A.forward.hpp"
#include "B.forward.hpp"
template<typename T> struct A
{
void RunA(B<T> *pB);
};
// A.impl.hpp
#include "A.decl.hpp"
#include "B.hpp"
template<typename T> void A< T >::
RunA(B<T> *pB)
{
// need to do something to B here
}
// A.hpp // this one should be included by code using A
#include "A.decl.hpp"
#include "A.impl.hpp"
// B.forward.hpp
template<typename T> struct B;
// B.decl.hpp
#include "B.forward.hpp"
#include "A.forward.hpp"
template<typename T> struct B
{
void RunB(A<T> *pA);
};
// B.impl.hpp
#include "B.decl.hpp"
#include "A.hpp"
template<typename T> void B< T >::
RunB(A<T> *pA)
{
// need to do something to A here
}
// B.hpp // this one should be included by code using B
#include "B.decl.hpp"
#include "B.impl.hpp"
Obviously all of these headers also need some sort of header guards that I omitted here. Important notice: .impl.hpp
headers are considered internal and should never be used by the outside code while .forward.hpp
, .decl.hpp
and .hpp
can be used anywhere.
This approach does introduce circular include dependencies, however this does not lead to problems: code structure produced by inclusion of headers ensures that code parts are included in the following order: forward declarations, class definitions, methods definitions.
You can separate the declarations and definitions of classes. Therefore you can separate the declarations and definitions of template classes...
You can separate the declarations and definitions of class methods. Therefore you can separate the declarations and definitions of template class methods:
template<typename T> struct B; // declaration
template<typename T> struct A { // definition
void RunA(B<T> *pB); // declaration
};
template<typename T> struct B { // definition
void RunB(A<T> *pA); // declaration
};
// definition
template<typename T>
void A<T>::RunA(B<T> *pB) {
// need to do something to B here
}
// definition
template<typename T>
void B<T>::RunB(A<T> *pA) {
// need to do something to A here
}