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
};
开发者_JS百科
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:
- Define each class in its header
- Have each header include the dependencies it needs
- Not **require** that the dependency succeed in defining the class, and forward-declare it as well.
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 */
A.hpp and A1.h should not include anything related to B or C.
Why does A
's implementation need to know about B
& C
at all? If the parent's implementation depends on details of a specific child, it seems like the inheritance isn't being used properly.
It seems likely you can just remove those includes and fix the problem that way.
Can you show us specifically why you need to include B
& C
within A
's header/implementation?
精彩评论