Include PROBLEM

Started by
6 comments, last by kroiz 23 years, 10 months ago
HI HI I need to include two files to my code. but i need each of the files to know the other. for instance suppose the two files are a.h and b.h if i type: #include "a.h" #include "b.h" then function in b.h don't "know" the class in a.h and vice versa. thank you for read and trying to help. Edited by - kroiz on 6/15/00 4:21:08 PM
0 error(s), 0 warning(s)
Advertisement
Maybe this example will help:

    class AClass;class BClass{AClass *pAClass;};class AClass{BClass *pBClass;};    


easy!
at the top of the a.h file put #include "b.h"
and at the top of the b.h file put #include "a.h"
does this help?

//end
Hi!

Also don''t forget the include guards. For example, if your header file is called a.h. It should have the form:

#ifndef __A_H__
#define __A_H__

//Here come the regular definitions in the header file
...
...
...

#endif //__A_H__

__A_H__ could be anything, but try to be consistent (i.e. somehow encode the name of the header file in it). It should also be unique for the entire project (i.e. don''t use the same symbol in two header files).

The include guards prevent you from including files multiple times (also recursively). This saves you from "Multiple Definition" errors, etc

Ciao,

MK42
Cyclic dependencies are often a sign for a fault in the design of your program. There are possibilities to remove such cyclic dependencies by identifying a common functionality of the classes in the two header files which would lend itself to inheritance (this methodology is also called "demotion"). Or there might be the possibility to create a new component (or class) which uses the services of the classes in your two header files and unite them therefore (this method is also called "escalation").

Perhaps it is even ok to keep both components which are the origin of the cyclic dependencies in one header and forward declare on of them before the other (take a look at baskuenens answer).

// file a.h
#ifndef INCLUDED_a
#define INCLUDED_a

// there needn't be a header inclusion just a forward declaration
// why? b is only used in name only (b*). To compile this
// the compiler needn't know the size of an object b, because
// pointers to objects have everytime the same size (size of a 32 bit pointer on an intel architecture)
class b;

class A{
b* m_b;
};

#endif

// file b.h
#ifndef INCLUDED_b
#define INCLUDED_b

// forward declaration
class a;

class b{
a* m_a;
};

#endif

// file a.cpp
#include "a.h"

// include b.h if you need to use it (say calling a function of it)
#include "b.h"

// ...

// file b.cpp
#include "b.h"

// include a.h if you need to use it (say calling a function of it)
#include "a.h"

// ...

Nevertheless: take a look if you can't abandon cyclic dependencies!!!!!! (They are bad (most times)! Believe me :-)

Bjoern

P.S.: If you want post the problem you want to solve with your cyclic dependencies. Perhaps someone can help you to avaid the cyclic nature of your solution...

Edited by - bjoern on June 16, 2000 7:54:39 AM
I often come across cyclic dependencies in my code. A lot of them used to be because I inlined a lot of functions in the headers. These functions often needed access to other class headers to operate, leading to the extra header inclusion. Moving these functions to the source file allowed me to move the #include into the source file, meaning the headers no longer needed to depend on each other.

There is one added complication though. Whereas forward-declaring a class to use its pointers is sufficient 99% of the time, the STL containers don''t like this. In order to use a list of MyClass*, you need to include the Myclass definition. This is due to a shortcoming with every STL implementation that I have seen which means it either requires a specialisation for your specific pointer type, otherwise it seems to need the destructor. If you know how to do that specialisation, then you''re usually ok.
Yeah, the STL is a different kind of a beast :-) Including the header file of a stl component (for example vector) won''t introduce cyclic dependencies, just dependencies and thats ok.
However if you are using a vector to store MyClass pointers it is like it is with normal classes used in a header - you need to include it''s declaration. If you are using something like
vector< MyClass* > * m_list;
you shouldn''t need to include the vector header - but I don''t think that it is practically (mostly performance wise) to acess every component via a pointer.

Cyclic dependencies are evil - "normal dependencies" are something to minimize but if you write small and performance critical classes (like vectors, matrices, etc.) you will want to inline the small class-functions - so there won''t be a way around dependencies/includes in the header and this is ok.

Perhaps sometimes the comilers will get fully ANSI C++ compatible and will allow to implement a template in the c file and not in the header and perhaps then there won''t be the need to implement a template class or function inline in a header...

Bjoern
quote:Original post by bjoern

If you are using something like
vector< MyClass* > * m_list;
you shouldn''t need to include the vector header


Sadly, you do. The vector class needs to be able to destroy the objects held within it. This involves calling the destructor explicitly (probably something to do with memory reuse: vector doesn''t release any memory until it is released itself, for example). If you had a vector of MyClass, it can just call ~MyClass() to destruct it. But if you give it a pointer type, there is no destructor defined. Most implementations therefore include specialisations for all the basic pointer types: char*, int*, float*, etc. But they can obviously not provide specialisations for your own class. And therefore the library doesn''t know how to destruct them. It seems to fall back on requiring the pointer''s class''s destructor (this seems to be incorrect behaviour to me, but all implementations seem to do it) and this is why it requires either the class definition, or a specialisation for your particular class.

If anyone has any more detailed comments on this, I''d be interested to hear them.

As for it not being efficient to access everything through a pointer... I think that is a very negligible performance penalty I usually store pointers rather than the actual objects as I nearly always need to store an object in more than one list.

This topic is closed to new replies.

Advertisement