• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 402
  • Last Modified:

Mutual include statements between two .h files

I have two .H files, one class in each

A
and
B

B is defined and has a variable of type A *
which means that B has an include "A.h"

now, I have a situation that calls for A to know B as well
meaning that A will have a B * variabile
and will also need to include "B.h"

thats mutual include

when compiling B.h, the complier will not continue reading the include A.h after the point that include "B.h" appears in A.h
and therefore B has no idea who is A


what can I do to have both "know" each other and escape the compiler error.

btw, each .h file has a ifdef clause

#ifndef _INCLUDE_CFIELDS_H
#define _INCLUDE_CFIELDS_H
...
#endif

using MS Visual Studio.NET 2003,

thanks
0
moshem
Asked:
moshem
  • 7
  • 4
  • 3
  • +1
2 Solutions
 
SteHCommented:
Is this include guard
#ifndef _INCLUDE_CFIELDS_H
#define _INCLUDE_CFIELDS_H
...
#endif
identical in each header? It should not be.
Try
#ifndef _INCLUDE_A_H
#define _INCLUDE_A_H
...
#endif
and
#ifndef _INCLUDE_B_H
#define _INCLUDE_B_H
...
#endif
0
 
moshemAuthor Commented:
it is not identical

one is the above

the second is:

#ifndef _INCLUDE_CFIELDS_H
#define _INCLUDE_CFIELDS_H
...
#endif
0
 
SteHCommented:
Sorry but
#ifndef _INCLUDE_CFIELDS_H
#define _INCLUDE_CFIELDS_H
...
#endif
and
#ifndef _INCLUDE_CFIELDS_H
#define _INCLUDE_CFIELDS_H
...
#endif
look identical to me.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
moshemAuthor Commented:
sorry, my bad.

the second is:

#ifndef _INCLUDE_CRULES_H
#define _INCLUDE_CRULES_H
...
#endif
0
 
stefan73Commented:
Hi moshem,
Use a class forward declaration:

class B;

class A{
    B* myB;
};

class B{
    A* myA;
}

This works fine, as long as you don't dereference B (you can't) -> You can only dereference B in methods which know already how B looks like.

Cheers!

Stefan
0
 
jkrCommented:
You'd usually use a foward declaration for that, e.g. like

//a.h
#ifndef A_H
#define A_H
#include "b.h"
#ifndef B_DEFINED
class B;
#endif
class A {

//...

B* pb;
};
#define A_DEFINED
#endif

//b.h
#ifndef B_H
#define B_H
#include "a.h"
#ifndef A_DEFINED
class A;
#endif
class B {

//...

A* pa;
};
#define B_DEFINED
#endif
0
 
stefan73Commented:
moshem,
It's a good habit to use a forward declaration of used class attributes in all class declarations, like:

A.h:

class B;
class A{
    B* myB;
    ...
};

B.h:
class A;
class B{
    A* myA;
}

(don't forget the #ifdef wrappers)

Include a class definition only if you need to inherit from another class.
Now you can simply do in all your .cpp files:

#include <A.h>
#include <B.h>

...without having to worry about the underlying include order. That pretty much decouples class dependencies and is as close as you can get in C++ in comparison to languages with a more advanced reference concept for class declarations (such as Java, Ruby, etc.)

0
 
moshemAuthor Commented:
well, I tried using forward declration the problem is I need to use the pointer to access members of the class so just defining the name wont cut it.

I need to have a way, to access the member funcitons of B from A using B *, and using forward declarations won't give me access to member functions AFAIK.

the current situations is that B includes A, has a pointer to A * and uses it's members.

now I need to have A include B, have a B * pointer and use at least one member function.

any ideas ?
0
 
jkrCommented:
>>the problem is I need to use the pointer to access members of the class

Move that code out of the header file and into the implementation file and you're rid of the problem. That's where it should go to anyway.
0
 
moshemAuthor Commented:
true, in this case I used only .h files and the code is in the method declaration, do I understand what you are saying , that spliting the code to an cpp file will solve the problem ? can you explain ?

btw, will I still need to use forward declaration ?

thanks.
0
 
jkrCommented:
>>that spliting the code to an cpp file will solve the problem ? can you explain ?

Yes, if you only are using pointers. If you start accessing members via that pointers, trouble will start again

>>btw, will I still need to use forward declaration ?

Yes.
0
 
moshemAuthor Commented:
>>Yes, if you only are using pointers. If you start accessing members via that pointers, trouble will start again

what do you mean ?

I want to do:

 B * p;

p->Method (arg1,arg2);


I will check it out and report back later on
0
 
jkrCommented:
>>>>Yes, if you only are using pointers. If you start accessing members via that pointers, trouble will start again
>>what do you mean ?

I mean that the trouble will start all over if you are actually using the pointers in the header file. That should go to the implementation file.
0
 
moshemAuthor Commented:
Ok, I tried it , I still dont know if this works since I have a problem with the forward declarations.

I used forward declrations like this:

struct associated_data_type;
struct field_entity_struct;
typedef type_field_entity_map_iterator;
struct field_struct;
class CFields;

all works except the typedef,when the compiler encounters the real typedef defenition in the original file it complains about redefinition with differnet base types.

the full defenition is:

typedef std::map <std::string, field_entity_struct>::iterator  type_field_entity_map_iterator;


how can I also forward these typedefs which are neccessary for the compilation ?

thanks
0
 
moshemAuthor Commented:
never mind, I just declared the typedef in it's full form in both .h files and it compiles ok.

if you have other better ideas let me know.

0
 
stefan73Commented:
If the typedef is not related to your classes (normally, it should!),
define the typedef in a generic, prologue-style .h file:

generic.h:
<some includes>
typedef std::map <std::string, field_entity_struct>::iterator  type_field_entity_map_iterator;

...and then make sure that every class definition file includes this file first. Be aware that by this, you add order dependencies to your includes, which is not good.

So check if you can place it into your classes - an iterator is normally belonging to a class.

BTW: Separating class definition and implementation is A Good Thing.

Imagine a larger project with lots of interdependent classes - implementation changes are normally more frequent than definition changes, so you don't have to recompile everything again (by make or otherwise) for a tiny implementation change.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 7
  • 4
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now