Hi people
I read a lot of docs before post it here, anf for my surprise this subject is extremely debated in some foruns and tutorials, either in C or C++ (specially) programming..(I use C++)
In big designs ( although you can do it in a small one, if you want ) sometimes you need to build a data structure based on another data structure.
Lets considere only 2 units: a.cpp / a.h and b.cpp / b.h.
Lets call them simply as A and B, for simple commodity...
// a.h
#ifndef A_H // avoid 2+ including
#define A_H // avoid 2+ including
struct a_t
{
uint8 a,b,c;
};
#endif // avoid 2+ including
// b.h
#ifndef B_H // avoid 2+ including
#define B_H // avoid 2+ including
#include a.h // need to know about a_t
struct b_t
{
a_t my_a; // type from a.h !!
uint8 c,d,e;
};
#endif // avoid 2+ including
// a.cpp
#include a.h // self include (C++ approach)
#include b.h // to know about b_t
void main(void)
{
b_t data; // a instance of b_t;
// using b_t type variable ....
data.my_a.a=1;
data.c=2;
};
Everything is ok: A depend on B, BUT not vice versa....easy...
Now imagine that A must create a new struct based on b_t (declared in b.h )
Lets modify a.h to:
// a.h
#ifndef A_H // avoid 2+ including
#define A_H // avoid 2+ including
#include "b.h" // to know about b_t type
struct a_t
{
uint8 a,b,c;
};
struct a1 // NEW !!!
{
b_t my_b; // from b.h !!!
uint32 t;
};
#endif // avoid 2+ including
Now start the confusion....
a.h wants to create a type based on a struct declared on b.h, so a.h must include b.h.
BUT, b.h was already including a.h, sine the beginning...
So we have a mutual depenedency, also called cyclical dependence...
I understood that the #ifdef XX_H statements (called "compilation guard" ) will make the compilation skipp over one of these files, since that after the first compilation, its definition will occur, so when the next file compile, it will find a already defined guard condition, skipping on it...
Forward declaration:
After many readings, I learned there is a solution for mutual inclusion SINCE IF the depenedence is based ONLY in pointers / references.
To use a_t in a b.h WITHOUT include a.h into b.h , you can do:
struct a_t; // forward declaration : like a prototype for functions...
struct b_t
{
a_t *my_a; // it is a pointer to the type, not a type it self !!!
}
BUT, not solve the case when you really need export structures between 2 files, when they depends each other.
I saw lot of rules been afirmed, but criticised late, and vice-versa.
The 2 polemic ones:
1- Only c (cpp) files can #include H files...
2- All #includes must be made into H files, so it can work alone...
Many tradeoffs were mentioned against the 2 rules above.
It seems there is not a "unique" true about it...
In my case, I´m in troubles due to cyclic depenedence.
I have a file xxx.h that simply ignores a type that was defined into another H file wich WAS really included into xxx.h>
The trick I did, is have a globals.h where I put some structures that causes this cyclical depenedcies.
It works, but is ugly and not professional.
Well, this example I wrote is just to ilustrate about the "nature" of this issue.
There can be some sintax error, some wrong detail, etc...BUT, in fact such cyclical condition exists and leads to a good headache in bigger design.
Some guys says it is a bad design, other says it is needed if the project gets complex / big.
My design has 82 filles...it´s not huuuggee, but enough big to reach such complexity.
Thanks in advance guys !!!
Ricardo Raupp
Do NOT cross-post your queries, please!
---Tom