I am having troubles with inclusion model of templates implementation and cyclic dependency of *.h and *.hpp files.
Let us imagine the following inheritance sequences of classes:
A->B->C,
A->A1,
B->B1, C->C1
where A, A1 are abstract classes.
A.h (Abstract class)
#ifndef A_H
#define A_H
template <class A>
{
//some code
virtual A() = 0;
};
#include "A.hpp"
#endif
A.hpp
#ifndef A_HPP
#define A_HPP
#include "B.h" //Circular dependency
#include "C.h" //Circular dependency
void create Object(A ** a, unsigned int code)
{
switch (code)
{
case 0: *a = new B(); break;
case 1: *a = new C();
};
}
#endif
B.h
#ifndef B_H
#define B_H
#include "A.h"
template <class T>
class B : public A <T>
{
//Some code
};
C.h
#ifndef C_H
#define C_H
#include "C.h"
template <class T>
class C : public B <T>
{
//Some code
};
A1.h (abstract class)
#ifndef A1_H
#define A1_H
#include "A.h"
template <class T>
class A1 : public A <T>
{
//Some code
};
#include "A.hpp"
#endif
A1.hpp
#ifndef A1_HPP
#define A1_HPP
#include "B1.h" //Circular dependency
#include "C1.h" //Circular dependency
void create Object(A1 ** a1, unsigned int code)
{
switch (code)
{
case 0: *a = new B1(); break;
case 1: *a = new C1();
};
#endif
B1.h
#ifndef B1_H
#define B1_H
#include "B.h"
template <class T>
class B1 : public B <T>
{
//Some code
};
C1.h
#ifndef C1_H
#define C1_H
#include "C.h"
template <class T>
class C1 : public C <T>
{
//Some code
};
How to make a reasonable including to avoid the circular dependency? I try to replace include directives with forward declarations, but unfortunately it was not enough for compiler…
A.hpp
#ifndef A_HPP
#define A_HPP
template <class T>
class A;
template <class T>
class B;
//some code
#endif
1.hpp
#ifndef A1_HPP
#define A1_HPP
template <class T>
class A;
template <class T>
class B;
//some code
#endif
You’ll need to:
If you do all of the above you’ll allow other code to include the headers in any order but they’ll still work in their “circulariness”. No my spelling checker didn’t know that word, as I just made it up.
In other words, you need to do things like this:
foo.h:
#ifndef FOO_H #define FOO_H #include "bar.h" class bar; // THIS IS THE CRITICAL LINE class foo { // ... uses bar } #endif /* FOO_H */bar.h
#ifndef BAR_H #define BAR_H #include "foo.h" class bar; // THIS IS THE CRITICAL LINE class bar { // ... uses foo } #endif /* BAR_H */